zoukankan      html  css  js  c++  java
  • 【BZOJ2821】作诗(Poetize)—(分块)

    传送门

    还算好的一道分块题了吧

    除了细节问题炸锅1h++以外

    考虑要询问出现偶数次的数的个数

    我们可以nnnsqrt{n}预处理出两个数组:

    num[i][j]num[i][j]表示jj这个数在前ii块中出现了多少次

    这样我们就可以O(1)O(1)求出一个数在第ii~jj块出现的次数

    val[i][j]val[i][j]表示第ii块到第jj块内出现了偶数次的数的个数

    这样对于每次询问,我们直接O(1)O(1)得到所有整块内的答案

    然后再对两边长为nsqrt{n}的区间统计一下每个数出现的次数,再和整块内的数的出现次数分类讨论一下得到答案

    复杂度O(nn+mn)O(nsqrt{n}+msqrt{n})

    其实由均值法分析的最适合的块的大小是nlognsqrt{nlog_n}

    但空间开不下就只能nsqrt{n}

    注意细节!!

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0;
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res;
    }
    const int N=100005;
    const int M=318;
    int n,c,buc[N],plc[N],m,cnt,blo,l[M],ans,r[M],num[M][N],a[N],val[M][M];
    int main(){
    	n=read(),c=read(),m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	blo=sqrt(n),cnt=(n-1)/blo+1;
    	for(int i=1;i<=n;i++)plc[i]=(i-1)/blo+1;
    	for(int i=1;i<=cnt;i++)l[i]=(i-1)*blo+1,r[i]=min(i*blo,n);
    	for(int i=1;i<=n;i++){
    		for(int j=plc[i];j<=cnt;j++){
    			num[j][a[i]]++;
    		}
    	}
    	for(int i=1;i<=cnt;i++){
    		int tmp=0;
    		for(int j=l[i];j<=n;j++){
    			if(buc[a[j]]&1)tmp++;
    			else if(buc[a[j]]>0)tmp--;
    			buc[a[j]]++;
    			if(j==r[plc[j]])val[i][plc[j]]=tmp;
    		}
    		memset(buc,0,sizeof(buc));
    	}
    	while(m--){
    		int x=(read()+ans)%n+1,y=(read()+ans)%n+1;
    		if(x>y) swap(x,y);ans=0;
    		if(plc[x]==plc[y]||plc[x]+1==plc[y]){
    			for(int i=x;i<=y;i++)buc[a[i]]++;
    			for(int i=x;i<=y;i++){
    				if(buc[a[i]]==0)continue;
    				if(!(buc[a[i]]&1))ans++;
    				buc[a[i]]=0;
    			}
    		}
    		else{
    			ans=val[plc[x]+1][plc[y]-1];
    			for(int i=x;i<=r[plc[x]];i++)buc[a[i]]++;
    			for(int i=l[plc[y]];i<=y;i++)buc[a[i]]++;//先全部加进桶里
    			for(int i=x;i<=r[plc[x]];i++){
    				if(buc[a[i]]==0)continue;
    				int tmp=num[plc[y]-1][a[i]]-num[plc[x]][a[i]];
    				if(tmp==0){//注意这里if语句的顺序
    					if(!(buc[a[i]]&1))ans++;
    				}
    				else if((tmp&1)&&(buc[a[i]]&1))ans++;
    				else if((!(tmp&1))&&(buc[a[i]]&1))ans--;
    				buc[a[i]]=0;
    			}
    			for(int i=l[plc[y]];i<=y;i++){
    				if(buc[a[i]]==0)continue;
    				int tmp=num[plc[y]-1][a[i]]-num[plc[x]][a[i]];
    				if(tmp==0){//注意这里if语句的顺序
    					if(!(buc[a[i]]&1))ans++;
    				}
    				else if((tmp&1)&&(buc[a[i]]&1))ans++;
    				else if((!(tmp&1))&&(buc[a[i]]&1))ans--;
    				buc[a[i]]=0;
    			}
    		}
    		cout<<ans<<'
    ';
    	}
    }
    
    
  • 相关阅读:
    java加载类的方法1.classloader 2.class.forName()
    servlet与线程与jdbc connection的关系
    static再次深入理解
    多线程读某个共享变量有时候也要给读方法加锁
    多线程读一个全局变量要不要加锁?还是说只是当修改全局变量的时候才要加锁?
    接口耗时打印并统计
    Java从设计模式[本场比赛状态转换武器]状态分析(State)模式
    Openstack中间DVR Part1 -- 东西走向的交通处理
    写酷“大神”的公开信
    从反思谈论阵列和指针的几个问题,腾讯的笔名
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366364.html
Copyright © 2011-2022 走看看