Hdu 5145 NPY and girls

来源:互联网 发布:遥感数据 编辑:程序博客网 时间:2024/05/16 01:12

 一个很普通的莫队题+可重集排列

莫队的说明网上已经很多了,我就不献丑了


直接来考虑添加端点或者删除端点的情况吧

添加 就是分子乘区间长度,分母乘当前位置的数的个数,然后更新数的个数

删除 就是分母乘区间长度,分子乘当前位置的数的个数,同样更新一下数的个数


莫队的我没有注意到的一个trick是

转移区间的时候优先更新右端点,然后左端点,否则可能出现右端点在左端点左边的情况


#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define LL long longconst int maxn = 31234;const LL mod = 1000000007;struct Ask{    int l,r;    int id;    LL ans;    void init(int i){        scanf("%d %d",&l,&r);        id = i;    }};Ask ask[maxn];int unit;bool cmpmo(Ask a,Ask b){    if(a.l / unit != b.l / unit)        return a.l < b.l;    return a.r < b.r;}bool cmpid(Ask a,Ask b){    return a.id < b.id;}LL cnt[maxn];int arr[maxn];LL rever[maxn];LL powerMod(LL x,LL n,LL mod){    LL ret = 1;    while(n){        if(n&1) (ret *= x) %= mod;        (x *= x) %= mod;        n >>=1;    }    return ret;}LL rev(int x){    if(rever[x] != -1)        return rever[x];    return rever[x] = powerMod(x,mod-2,mod);}LL siz;LL renew(LL ans,int pos,bool adder){    LL & x = cnt[arr[pos]];    if(adder){        x++;        siz++;        (ans *= siz) %= mod;        (ans *= rev(x)) %= mod;    }    else{        (ans *= x) %= mod;        (ans *= rev(siz)) %= mod;        siz--;        x--;    }    return ans;}int main(){    int T;    int n,m;    memset(rever,-1,sizeof(rever));    scanf("%d",&T);    while(T-- && ~scanf("%d %d",&n,&m)){        unit = (int)sqrt(n*1.0);        for(int i=1;i<=n;i++){            scanf("%d",&arr[i]);        }        for(int i=0;i<m;i++){            ask[i].init(i);        }        sort(ask,ask+m,cmpmo);        LL ans = 1;        siz = 0;        memset(cnt,0,sizeof(cnt));        for(int i=ask[0].l;i<=ask[0].r;i++){            ans = renew(ans,i,true);        }        ask[0].ans = ans;        int st,ed;        for(int i=1;i<m;i++){            st = min(ask[i].r,ask[i-1].r);            ed = max(ask[i].r,ask[i-1].r);            for(int id=st+1;id<=ed;id++)                ans = renew(ans,id,ed==ask[i].r);            st = min(ask[i].l,ask[i-1].l);            ed = max(ask[i].l,ask[i-1].l);            for(int id=st;id<ed;id++)                ans = renew(ans,id,st==ask[i].l);            ask[i].ans = ans;        }        sort(ask,ask+m,cmpid);        for(int i=0;i<m;i++){            printf("%I64d\n",ask[i].ans);        }    }    return 0;}


0 0