bzoj 2821: 作诗(Poetize) (分块)
2016-12-10 17:44
323 查看
2821: 作诗(Poetize)
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 2706 Solved: 771
[Submit][Status][Discuss]
Description
神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗。由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一
些汉字构成诗。因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次。而且SHY认
为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!)。于是SHY请LYD安排选
法。LYD这种傻×当然不会了,于是向你请教……问题简述:N个数,M组询问,每次问[l,r]中有多少个数出现正偶
数次。
Input
输入第一行三个整数n、c以及m。表示文章字数、汉字的种类数、要选择M次。第二行有n个整数,每个数Ai在[1, c]间,代表一个编码为Ai的汉字。接下来m行每行两个整数l和r,设上一个询问的答案为ans(第一个询问时ans=0),
令L=(l+ans)mod n+1, R=(r+ans)mod n+1,若L>R,交换L和R,则本次询问为[L,R]。
Output
输出共m行,每行一个整数,第i个数表示SHY第i次能选出的汉字的最多种类数。Sample Input
5 3 51 2 2 3 1
0 4
1 2
2 2
2 3
3 5
Sample Output
20
0
0
1
HINT
对于100%的数据,1<=n,c,m<=10^5Source
By lydrainbowcat分块,预处理出两个数组
①f[i][j]表示第i块到第j块的答案
②cnt[i][j]表示从第一个块左端点到第i个块的右端点j出现的次数
则每次询问考虑左右残留部分对答案的影响即可。
那么,如何考虑影响?
把残留部分扔到一个数组里,排序,统计出现了的数出现的次数,与已统计的完整的块内出现的次数比较,利用奇偶性判断影响。。。 注意:千万别偷懒扔到STL容器里,会TLE的,乖乖排序。。。。。。
代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<cstdio> #include<cstring> #include<string> #include<climits> #include<queue> #include<stack> #include<cmath> #include<map> #include<set> #define N 100001 using namespace std; int read() { int x=0,f=1;char ch; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,c,m,ans,B; int a ,tot,cnt[321] ,bel ; int l[321],r[321],f[321][321]; int num ; void init() { int ret=0; for(int i=1;i<=tot;i++) { int now=i;ret=0; for(int j=l[i];j<=n;j++) { num[a[j]]++; if(num[a[j]]%2==0&&num[a[j]])ret++; else if(num[a[j]]!=1)ret--; if(j==r[now])f[i][now++]=ret; } for(int j=1;j<=c;j++)num[j]=0; }int now=1; for(int i=1;i<=tot;i++) for(int j=l[i];j<=r[i];j++) cnt[i][a[j]]++; for(int i=1;i<=tot;i++) for(int j=1;j<=c;j++) cnt[i][j]+=cnt[i-1][j]; } int tmp ; int hash ,sz; void solve(int x,int y) { sz=0; int L=(x-1)/B+2,R=(y-1)/B;ans=f[L][R]; int l1=x,r1=l[L]-1,l2=r[R]+1,r2=y; if(L>R) { ans=0;int num=0; for(int i=x;i<=y;i++) tmp[++sz]=a[i]; sort(tmp+1,tmp+1+sz);tmp[sz+1]=0; for(int i=1;i<=sz+1;i++) { if(i!=1&&tmp[i]!=tmp[i-1]) { if((num&1)==0) ans++;num=0; }num++; }return; }int num=0; for(int i=l1;i<=r1;i++) tmp[++sz]=a[i]; for(int i=l2;i<=r2;i++) tmp[++sz]=a[i]; sort(tmp+1,tmp+1+sz);tmp[sz+1]=0; for(int i=1;i<=sz+1;i++) { if(i!=1&&tmp[i]!=tmp[i-1]) { if((num&1)==0) { int s=cnt[R][tmp[i-1]]-cnt[L-1][tmp[i-1]]; if(!s)ans++; } else { int s=cnt[R][tmp[i-1]]-cnt[L-1][tmp[i-1]]; if(s&1)ans++; else if(s)ans--; }num=0; }num++; } } int main() { // freopen("in.txt","r",stdin); // freopen("my.txt","w",stdout); n=read(),c=read(),m=read();B=sqrt(n); for(int i=1;i<=n;i++) { bel[i]=(i-1)/B+1; if(!l[bel[i]])l[bel[i]]=i; r[bel[i]]=i;a[i]=read(); }tot=(n-1)/B+1;init(); for(int i=1;i<=m;i++) { int x=read(),y=read(); x=(x+ans)%n+1,y=(y+ans)%n+1; if(x>y)swap(x,y);solve(x,y); printf("%d\n",ans); } }
相关文章推荐
- 【分块】BZOJ2821 作诗(Poetize)
- 【BZOJ2821】作诗(Poetize) 分块
- BZOJ 2821: 作诗(Poetize)|分块
- [bzoj] 2821 作诗(Poetize) || 分块
- bzoj 2821: 作诗(Poetize) 分块
- 分块-bzoj2821: 作诗(Poetize)
- BZOJ 2821: 作诗(Poetize)( 分块 )
- BZOJ 2821 作诗(Poetize) 分块
- BZOJ 2821 作诗(Poetize)(分块)
- bzoj2821: 作诗(Poetize)【分块】
- 【bzoj2821】作诗(Poetize) 分块
- [BZOJ 2821] 作诗(Poetize) 【分块】
- 【分块】bzoj2821 作诗(Poetize)
- BZOJ 2821 作诗(Poetize) 分块
- bzoj 2821: 作诗(Poetize)【分块】
- BZOJ 2821: 作诗(Poetize) [分块]
- BZOJ2821 作诗(Poetize) 【分块】
- BZOJ 2821 作诗(Poetize) 分块
- BZOJ 2821 作诗(Poetize) 分块
- 【bzoj2821】【作诗】【分块】