您的位置:首页 > 其它

hdu5145 NPY and girls 莫队算法,分块

2015-08-26 23:52 399 查看
莫队算法可以离线解决区间查询的问题,dp[i][j]可以O(1)得到dp[i+1][j]或dp[i][j+1],将l分为sqrt(l)块,按照块排序,再按照r排序,理论复杂度nsqrt(n);

#include<iostream>
#include<cstring>
#include<cstdio>
#include<ostream>
#include<istream>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define fi first
#define se second
#define ll long long
#define pii pair<int,int>
#define inf (1<<30)
#define PI acos(-1.0)
#define eps 1e-8
#define pb push_back
using namespace std;
const int maxn=110005;
const ll mod=1000000007;
int c[maxn];
int num[maxn];
int n,m;
int block;
struct Node
{
    int l,r;
    int id;
    ll ans;
}node[maxn];
ll inv[maxn];
bool cmp(const Node& u,const Node& v)
{
    if(u.l/block!=v.l/block)
        return u.l/block<v.l/block;
    return u.r<v.r;
}
bool cmp2(const Node& u,const Node& v)
{
    return u.id<v.id;
}
ll powMod(ll a,ll b)
{
    if(b==0) return 1;
    ll ans=powMod(a,b/2);
    ans=ans*ans%mod;
    if(b&1)
        ans=ans*a%mod;
    return ans;
}
int main()
{
    for(int i=0;i<=30000;i++) inv[i]=powMod(i,mod-2);
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
        block=(int)sqrt(30000.0);
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&node[i].l,&node[i].r);
            node[i].id=i;
        }
        sort(node+1,node+m+1,cmp);
        memset(num,0,sizeof(num));
        int tot=0;
        ll ans=1;
        int L=1,R=0;
        for(int i=1;i<=m;i++) {
            while(R<node[i].r) {
                R++;tot++;
                num[c[R]]++;
                ans=ans*tot%mod*inv[num[c[R]]]%mod;
            }
            while(R>node[i].r) {
                ans=ans*inv[tot]%mod*num[c[R]]%mod;
                num[c[R]]--;
                R--; tot--;
            }
            while(L<node[i].l) {
                ans=ans*inv[tot]%mod*num[c[L]]%mod;
                num[c[L]]--;
                L++; tot--;
            }
            while(L>node[i].l) {
                L--; tot++;
                num[c[L]]++;
                ans=ans*tot%mod*inv[num[c[L]]]%mod;
            }
            node[i].ans=ans;
        }
        sort(node+1,node+m+1,cmp2);
        for(int i=1;i<=m;i++)
            printf("%I64d\n",node[i].ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: