【BZOJ】【P2821】【作诗(Poetize)】【题解】【分块】

传送门:

http://www.lydsy.com/JudgeOnline/problem.php?id=2821

蒟蒻的分块第一题,常数T成翔,

蒟蒻没优化前跑n=m=c=1e5的大点4000+ms,标程2000+ms
加读入优化3500+ms
删掉不必要的memset 3000+ms
然后把vis数组改成记录当前方案数而不是01,再去一个memset, 2184ms
交到bzoj终于过了……

/*
	ID:zky
	OJ:BZOJ
	Index:2821
	Language:C++
*/
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std;
const int maxn=int(1e5)+11;
const int sqrtn=320;
int n,m,t;
int a[maxn],b[maxn],c[maxn],vis[maxn],ans=0;
int st[maxn],ed[maxn],s[sqrtn],e[sqrtn];
int d[sqrtn][sqrtn],q[maxn];
int sqrn,bksz,tot;
inline int calc(int k,int x,int y){
	if(x>y)return 0;
	int l,r,mid;
	l=st[k];r=ed[k];
	while(l<r){
		mid=l+r>>1;
		if(b[mid]<x)
			l=mid+1;
		else
			r=mid;
	}
	if(b[l]>=x)l--;
	x=l;
	l=st[k];r=ed[k];
	while(l<r){
		mid=l+r>>1;
		if(b[mid]>y)
			r=mid;
		else
			l=mid+1;
	}
	if(b[l]>y)l--;
	y=l;
	return y-x;
}
int getint(){
	int res=0;
	int ok=0;
	char ch;
	while(1){
		ch=getchar();
		if(ch>='0'&&ch<='9'){
			res*=10;
			res+=ch-'0';
			ok=1;
		}else
			if(ok)break;
	}
	return res;
}
int main(){
	scanf("%d%d%d",&n,&t,&m);
	for(int i=1;i<=n;i++)a[i]=getint();
	for(int i=1;i<=n;i++)c[a[i]]++;
	for(int i=1;i<=t;i++){
		st[i]=tot+1;
		tot+=c[i];
		ed[i]=tot;
	}
	memset(c,0,sizeof(c));
	for(int i=1;i<=n;i++)
		b[st[a[i]]+c[a[i]]]=i,c[a[i]]++;

	sqrn=int(sqrt(n));bksz=n/sqrn;
	for(int i=1;i<=sqrn;i++){
		s[i]=(i-1)*bksz+1;
		e[i]=i*bksz;
	}
	if(e[sqrn]<n){
		sqrn++;
		s[sqrn]=e[sqrn-1]+1;
		e[sqrn]=n;
	}
	for(int i=1;i<=sqrn;i++){
		memset(c,0,sizeof(c)); ans=0;
		for(int j=i;j<=sqrn;j++){
			for(int k=s[j];k<=e[j];k++){
				c[a[k]]++;
				if(c[a[k]]>1&&(c[a[k]]&1)) ans--;
				else if((c[a[k]]&1)==0) ans++;
			}
			d[i][j]=ans;
		}
	}
	
	ans=0;
	for(int stp=1;stp<=m;stp++){
		int x,y,l,r;
		x=getint();y=getint();
		x=(x+ans)%n+1;y=(y+ans)%n+1;
		if(x>y)swap(x,y);
		int *esqrn = e + sqrn;
		for(int i=1;i<=sqrn;i++)if(e[i]>=x){l=i;break;}
		for(int i=sqrn;i>=1;i--)if(s[i]<=y){r=i;break;}	
		ans=d[l+1][r-1];
		if(l==r){
			for(int i=x;i<=y;i++){
				if(vis[a[i]]!=stp){
					vis[a[i]]=stp;
					c[a[i]]=1;
				}else{
					c[a[i]]++;
					if(c[a[i]]&1)ans--;else ans++;
				}
			}
			printf("%d\n",ans);
			continue;
		}
		int cnt=0;
		for(int i=x;i<=e[l];i++){
			if(vis[a[i]]!=stp){
				vis[a[i]]=stp;
				c[a[i]]=1;
				q[++cnt]=a[i];
			}else c[a[i]]++;
		}
		for(int i=s[r];i<=y;i++){
			if(vis[a[i]]!=stp){
				vis[a[i]]=stp;
				c[a[i]]=1;
				q[++cnt]=a[i];
			}else c[a[i]]++;			
		}
		for(int i=1;i<=cnt;i++){
			int k=calc(q[i],s[l+1],e[r-1]);
			if(k==0){
				if((c[q[i]]&1)||!c[q[i]])ans+=0;else ans+=1;
			}else
			if((k&1)&&(c[q[i]]&1))ans++;
			else if(!(k&1)&&(c[q[i]]&1))ans--;
		}
		printf("%d\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了python应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值