• P4135 作诗


    https://www.luogu.com.cn/problem/P4135
    https://darkbzoj.tk/problem/2821
    前缀和写的时候一开始原数组、前缀和数组分开来的,结果 bzoj MLE,和在一起才过的。。。
    给定一个长度为 (n) 的数列,(m) 个询问,每次问 ([l,r]) 中有多少种数的出现次数为偶数,强制在线,(n,m,max{a_i}le 10^5)

    区间问题,但线段树啥的又不好维护,考虑分块
    单独维护每个块的信息然后一个个合并肯定没戏,所以考虑每次询问只合并边角块和中间一部分整块的信息
    这样需要一个 (f_{l,r}) 来表示 ([l,r]) 块的答案,然后枚举边角块里的没一个元素,记录下每一个值出现了多少次,容易知道可以按照下面两条规则统计最终答案

    • 如果一个值在整块中出现了奇数次,或者没出现,那么如果在整块出现的次数和在两个边角块出现的次数的奇偶性相同,则这个值一共出现了偶数次,答案加一
    • 如果在整块中出现了偶数次,且不为零,那么如果在两个边角块中出现了奇数次,答案减一

    那么也就需要一个 (sum_{i,k}) 表示前 (i) 块,(k) 出现了几次
    按照上面的想法,也就可以 (O(nsqrt n)) 的预处理出 (f) 了(由 (f_{l,r-1}) 推知 (f_{l,r})

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define reg register
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=-1;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return x*y;
    }
    #define N 100005
    #define SQRTN 320
    int n,m,B,c;
    int block[N],a[N];
    int L[SQRTN],R[SQRTN],sum[SQRTN][N],f[SQRTN][SQRTN];
    int tmp[N];
    inline void pre(){
    	for(reg int i=1;i<=block[n];i++)
    		for(reg int j=1;j<=c;j++) sum[i][j]+=sum[i-1][j];
    	for(reg int i=1;i<=block[n];i++){
    		for(reg int j=L[i];j<=R[i];j++) tmp[a[j]]++;
    		for(reg int j=L[i];j<=R[i];j++) f[i][i]+=(tmp[a[j]]&&!(tmp[a[j]]&1)),tmp[a[j]]=0;
    		for(reg int j=i+1;j<=block[n];j++){
    			for(reg int k=L[j];k<=R[j];k++) tmp[a[k]]++;
    			f[i][j]=f[i][j-1];
    			for(reg int kk=L[j],k;kk<=R[j];kk++)if(tmp[a[kk]]){
    				k=a[kk];
    				if(sum[j-1][k]-sum[i-1][k]>0&&!((sum[j-1][k]-sum[i-1][k])&1)) f[i][j]-=(tmp[k]&1);
    				//[i,j-1] 上 k 的个数为偶数,且不等于 0,则 tmp[k] 为奇数答案就减一
    				else if((tmp[k]&1)==((sum[j-1][k]-sum[i-1][k])&1)) f[i][j]++;
    				//为奇数,或为 0,则 tmp[k] 与之前 k 的个数奇偶性相同,f[i][j] 就加一
    				tmp[k]=0;
    			}
    		}
    	}
    }
    //inline void print(){
    //	puts("block :");
    //	for(reg int i=1;i<=n;i++) printf("%d : %d,left : %d,right : %d
    ",i,block[i],L[block[i]],R[block[i]]);
    //	puts("
    sum :");
    //	for(reg int i=1;i<=block[n];i++){
    //		printf("block %d :
    ",i);
    //		for(reg int j=1;j<=c;j++) printf("%d ",sum[i][j]);
    //		puts("
    ");
    //	}
    //	puts("
    f :");
    //	for(reg int i=1;i<=n;i++){
    //		for(reg int j=i;j<=block[n];j++) printf("f[%d][%d]=%d  ",i,j,f[i][j]);
    //		puts("");
    //	}
    //}
    int main(){
    	n=read();c=read();m=read();B=std::sqrt(n);
    	std::memset(L,0x3f,sizeof L);
    	for(reg int i=1;i<=n;i++){
    		a[i]=read();
    		block[i]=block[i-1]+(!((i-1)%B));
    		sum[block[i]][a[i]]++;
    		R[block[i]]=std::max(R[block[i]],i);L[block[i]]=std::min(L[block[i]],i);
    	}
    	pre();
    //		print();
    	reg int l,r,bl,br;int ans=0;
    	while(m--){
    		l=(ans+read())%n+1;r=(ans+read())%n+1;
    		if(l>r) l^=r,r^=l,l^=r;
    		bl=block[l];br=block[r];
    		if(bl==br){
    			for(reg int i=l;i<=r;i++) tmp[a[i]]++;
    			ans=0;
    			for(reg int i=l;i<=r;i++) ans+=(tmp[a[i]]&&!(tmp[a[i]]&1)),tmp[a[i]]=0;
    			printf("%d
    ",ans);
    			continue;
    		}
    		for(reg int i=l;i<=R[bl];i++) tmp[a[i]]++;
    		for(reg int i=L[br];i<=r;i++) tmp[a[i]]++;
    		ans=f[bl+1][br-1];
    		for(reg int k,i=l;i<=R[bl];i++)if(tmp[a[i]]){
    			k=a[i];
    			if(sum[br-1][k]-sum[bl][k]>0&&!((sum[br-1][k]-sum[bl][k])&1)) ans-=(tmp[k]&1);
    			else if((tmp[k]&1)==((sum[br-1][k]-sum[bl][k])&1)) ans++;
    			tmp[k]=0;
    		}
    		for(reg int k,i=L[br];i<=r;i++)if(tmp[a[i]]){
    			k=a[i];
    			if(sum[br-1][k]-sum[bl][k]>0&&!((sum[br-1][k]-sum[bl][k])&1)) ans-=(tmp[k]&1);
    			else if((tmp[k]&1)==((sum[br-1][k]-sum[bl][k])&1)) ans++;
    			tmp[k]=0;
    		}
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    学习笔记5_Day09_网站访问量统计小练习
    学习笔记4_ServletContext(重要整个Web应用的动态资源之间共享数据)
    学习笔记03_Day09-----Servle与反射()
    学习笔记2_Day09_servlet的细节
    学习笔记1_Day09_Servlet
    OC对数组排序的方法
    sqlite事务处理
    封装数据库
    JsonModel的使用
    RBAC表
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/13531824.html
Copyright © 2020-2023  润新知