NPY and girls

NPY and girls

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5145

莫队算法

注意到没有修改区间的操作,使用莫队算法:将整个区间分成若干个块,将询问区间按块优先升序排序,同块内按区间右界升序排序,添加一个元素,满足条件的值sum就变为sum=(sum*times[a[r]]/(r-l+1));减少一个值同理。从第一个区间一直推到最后一个区间即可。(之前TLE一直以为是区间大小的问题,现在发现是这句话while(x<0)x+=M,不过因为这题M比较大,改改区间居然被我水过去了...)

代码如下:

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define N 30005
  6 #define M 1000000007
  7 #define LL long long
  8 #define B 250/**((int)sqrt((double)n)) sqrt(n) will be TLE**/
  9 #define mst(x) memset(x,0,sizeof(x))
 10 using namespace std;
 11 LL times[N];
 12 LL T,n,m,x,y;
 13 LL a[N];
 14 struct nod{
 15     LL l,r,no,value;
 16 }q[N];
 17 LL exGCD(LL a,LL b){
 18     if(b==0){
 19         x=1;
 20         y=0;
 21         return a;
 22     }
 23     LL r=exGCD(b,a%b);
 24     LL tmp=x;
 25     x=y;
 26     y=tmp-(a/b)*y;
 27     return r;
 28 }
 29 bool cmp_by_range(nod x,nod y){
 30     if(x.l/B==y.l/B){
 31         return x.r<y.r;
 32     }else return (x.l/B<y.l/B);
 33 }
 34 bool cmp_by_no(nod x,nod y){
 35     return x.no<y.no;
 36 }
 37 void init(){
 38     mst(times);
 39     scanf("%I64d%I64d",&n,&m);
 40     for(LL i=0;i<n;++i)
 41         scanf("%I64d",&a[i]);
 42     for(LL i=0;i<m;++i){
 43         LL l,r;
 44         scanf("%I64d%I64d",&l,&r);
 45         l--,r--;
 46         q[i].l=l;
 47         q[i].r=r;
 48         q[i].no=i;
 49         q[i].value=0;
 50     }
 51     sort(q,q+m,cmp_by_range);
 52 }
 53 void solve(){
 54     LL l=q[0].l,r=q[0].r,sum=1;
 55     times[a[l]]++;
 56     for(LL i=l+1;i<=r;++i){
 57         times[a[i]]++;
 58         exGCD(times[a[i]],M);
 59         while(x<0)x+=M;
 60         sum=((sum*(i-l+1))%M*x)%M;
 61     }
 62     q[0].value=sum;
 63     for(LL i=1;i<m;++i){
 64         //l=q[i-1].l,r=q[i-1].r;
 65         while(r<q[i].r){
 66             r++;
 67             times[a[r]]++;
 68             exGCD(times[a[r]],M);
 69             while(x<0)x+=M;
 70             sum=((sum*(r-l+1))%M*x)%M;
 71         }
 72         while(r>q[i].r){
 73             exGCD((r-l+1),M);
 74             while(x<0)x+=M;
 75             sum=((sum*times[a[r]])%M*x)%M;
 76             times[a[r]]--;
 77             r--;
 78         }
 79         while(l<q[i].l){
 80             exGCD((r-l+1),M);
 81             while(x<0)x+=M;
 82             sum=((sum*times[a[l]])%M*x)%M;
 83             times[a[l]]--;
 84             l++;
 85         }
 86         while(l>q[i].l){
 87             l--;
 88             times[a[l]]++;
 89             exGCD(times[a[l]],M);
 90             while(x<0)x+=M;
 91             sum=((sum*(r-l+1)%M)*x)%M;
 92         }
 93         q[i].value=sum;
 94     }
 95 }
 96 int main(void){
 97     scanf("%I64d",&T);
 98     while(T--){
 99         init();
100         solve();
101         sort(q,q+m,cmp_by_no);
102         for(LL i=0;i<m;++i)
103             printf("%I64d\n",q[i].value);
104     }
105 }

 

posted @ 2016-08-14 10:51  barriery  阅读(1230)  评论(0编辑  收藏  举报