• bzoj2821: 作诗(Poetize)


    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2821

    思路:分块大法好。。。

    分成sqrt(n)块,先预处理出连续的块的答案,f[i][j]表示第i块到第j块的答案。

    然后再开一个前缀和数组sum[i][j]表示前i个块第j种字符出现的次数。

    对于一组询问[l,r],先得出连续的块的答案。

    对于分散的两端的块,暴力考虑每个数对答案的贡献即可。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=100010,maxb=320;
    using namespace std;
    int n,c,m,sum[maxb][maxn],f[maxb][maxb],a[maxn],sz,cnt,bel[maxn],l[maxn],r[maxn],tsum[maxn],ans,tmp[maxn];
    
    void work(){
    	int x,y,L,R;scanf("%d%d",&x,&y);
    	x=(x+ans)%n+1,y=(y+ans)%n+1,ans=0;
    	if (x>y) swap(x,y);
    	//printf("%d %d
    ",x,y);
    	L=bel[x],R=bel[y];
    	if (L==R){
    		for (int i=x;i<=y;i++) tsum[a[i]]=0;
    		for (int i=x;i<=y;i++)
    			if ((++tsum[a[i]])!=1)
    				ans+=(tsum[a[i]]&1)?-1:1;
    	}
    	else{
    		ans=f[L+1][R-1];
    		//printf("ans%d %d %d
    ",L,R,ans);
    		for (int i=x;i<=r[L];i++) tsum[a[i]]=sum[R-1][a[i]]-sum[L][a[i]];
    		for (int i=l[R];i<=y;i++) tsum[a[i]]=sum[R-1][a[i]]-sum[L][a[i]];
    		//for (int i=1;i<=c;i++) printf("tsum%d
    ",tsum[i]);
    		for (int i=x;i<=r[L];i++)
    			if (++tsum[a[i]]!=1)
    				ans+=(tsum[a[i]]&1)?-1:1;
    		for (int i=l[R];i<=y;i++)
    			if (++tsum[a[i]]!=1)
    				ans+=(tsum[a[i]]&1)?-1:1;
    	}
    	printf("%d
    ",ans);
    }
    
    int main(){
    	scanf("%d%d%d",&n,&c,&m),sz=sqrt(n),cnt=n/sz+(n%sz!=0);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for (int i=1;i<=n;i++) bel[i]=(i-1)/sz+1;
    	for (int i=1;i<=n;i++){r[bel[i]]=i;if (!l[bel[i]]) l[bel[i]]=i;}
    	for (int i=1;i<=cnt;i++){
    		for (int j=1;j<=c;j++) sum[i][j]=sum[i-1][j];
    		for (int j=l[i];j<=r[i];j++) sum[i][a[j]]++;
    	}
    	for (int i=1;i<=cnt;i++){
    		for (int j=1;j<=c;j++) tsum[j]=0;int tmp=0;
    		for (int j=i;j<=cnt;j++){
    			for (int k=l[j];k<=r[j];k++)
    				if (tsum[a[k]]++) tmp+=(tsum[a[k]]&1)?-1:1;
    			f[i][j]=tmp;
    		}
    	}
    	//for (int i=1;i<=cnt;i++) printf("%d %d
    ",l[i],r[i]);
    	/*for (int i=1;i<=cnt;i++,puts(""))
    		for (int j=1;j<=cnt;j++)
    			printf("%d ",f[i][j]);*/
    	for (int i=1;i<=m;i++) work();
    	return 0;
    }


  • 相关阅读:
    response.redirect on asp.net is a 302 jump action
    什么吃掉了我的硬盘?
    百度流量统计将会影响搜索的排名
    发邮件 python
    bottle template usage
    想提神,喝中药,咖啡可可没用的
    企业退信的常见问题?
    用UnixBench测试VPS性能 判别是否值得购买
    域名注册及免费空间and企业邮箱
    LNMP一键安装包是什么?
  • 原文地址:https://www.cnblogs.com/thythy/p/5493539.html
Copyright © 2020-2023  润新知