【分块】P4135 作诗

分块太暴力惹...

没做出来。看了题解qaq

分析:

两头$\sqrt{n}$暴力维护

预处理ans[i][j],sum[i][j]

sum[i][j]是一个前缀和,前i块值为j的数量

ans[i][j]表示第i块到第j块的答案总和

询问的时候先做两头,最后把ans[][]加上去就好了!

主要难点在预处理和卡常

 1 #pragma GCC optimize(3)
 2 #pragma GCC optimize(2)
 3 #pragma GCC optimize("Ofast")
 4 #include<bits/stdc++.h>
 5 using namespace std;
 6 inline int read(){
 7     int ans=0,f=1;char chr=getchar();
 8     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
 9     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
10     return ans*f;
11 }const int M=1e5+5,N=320;
12 int sum[N][M],ans[N][N],n,c,m,x,y,bl[M],k,a[M],cnt[M],lst,tmp,i,j,now;
13 int Query(int l,int r){
14     tmp=0;
15     if(bl[l]==bl[r]){
16         for(i=l;i<=r;++i){
17             ++cnt[a[i]];
18             if(!(cnt[a[i]]&1)) ++tmp;
19             else if(cnt[a[i]]>2) --tmp;
20         }for(i=l;i<=r;i++) --cnt[a[i]];
21         return tmp;
22     }else{
23         for(i=l;i<=bl[l]*k;++i){
24             ++cnt[a[i]];
25             if(!((cnt[a[i]]+sum[bl[r]-1][a[i]]-sum[bl[l]][a[i]])&1)) ++tmp;
26             else if(cnt[a[i]]+sum[bl[r]-1][a[i]]-sum[bl[l]][a[i]]>2) --tmp;
27         }
28         for(i=(bl[r]-1)*k+1;i<=r;i++){
29             ++cnt[a[i]];
30             if(!((cnt[a[i]]+sum[bl[r]-1][a[i]]-sum[bl[l]][a[i]])&1)) ++tmp;
31             else if(cnt[a[i]]+sum[bl[r]-1][a[i]]-sum[bl[l]][a[i]]>2) --tmp;
32         }
33         for(i=l;i<=bl[l]*k;i++) --cnt[a[i]];
34         for(i=(bl[r]-1)*k+1;i<=r;i++) --cnt[a[i]];
35         tmp+=ans[bl[l]+1][bl[r]-1];    
36         return tmp;
37     }
38 }
39 signed main(){
40     n=read(),c=read(),m=read();k=sqrt(n)+1;
41     for(i=1;i<=n;++i) a[i]=read();
42     for(i=1;i<=n;++i) bl[i]=(i-1)/k+1,++sum[bl[i]][a[i]];
43     for(i=1;i<=bl[n];++i)for(j=1;j<=c;++j)sum[i][j]+=sum[i-1][j];
44     for(i=1;i<=bl[n];++i){
45         for(j=(i-1)*k+1,now=0;j<=n;++j){
46             cnt[a[j]]++;
47             if(!(cnt[a[j]]&1)) ++now;
48             else if(cnt[a[j]]>2) --now;
49             ans[i][bl[j]]=now;
50         }for(j=i*k-k+1;j<=n;++j)--cnt[a[j]];
51     }while(m--){
52         x=read(),y=read(),x=(x+lst)%n+1,y=(y+lst)%n+1;
53         if(x>y) swap(x,y);
54         printf("%d\n",lst=Query(x,y));
55     }return 0;
56 }

 

 

posted @ 2019-07-27 16:49  zheng_liwen  阅读(139)  评论(0编辑  收藏  举报
/*去广告*/