ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1705E Mark and Professor Koro 题解

2022-07-18 18:37:46  阅读:259  来源: 互联网

标签:rt tmp 数字 题解 Professor mid down CF1705E 改成


可能更好的阅读体验

题目传送门

题目大意

黑板上有 \(n\) 个数字 \(a_1,a_2,\dots,a_n\),现在你可以将黑板上相同的两个数字 \(x\) 擦掉,然后写上 \(x+1\),求最后能得到的最大数字。
当然你需要支持单点修改。
\(1\le n,q,a_i\le 2\times10^5\)

题目解析

不难发现题目给定的操作比较像二进制加法。如果把所有能够合并的数字都合并,那么每个数字最多出现一次,如果出现了数字 \(x\) 那么就说明二进制下从右往左第 \(x\) 位是 \(1\),否则是 \(0\)。
考虑修改其实就是删去一个数字,然后加上一个数字。如果说把 \(a_x\) 改为 \(y\),也就是减去 \(2^{a_x}\),加上 \(2^{y}\)。
这样也就是维护一个大整数。

考虑加上一个数字,如果这一位是 \(0\),直接把这一位改成 \(1\),否则找到更高位出现的第一个 \(0\),把这个 \(0\) 改成 \(1\),然后把这一段 \(1\) 改成 \(0\)。
删除其实是一样的。如果这一位是 \(1\),就把这一位改成 \(0\),否则找到更高位的第一个 \(1\),改成 \(0\),然后把连续的 \(1\) 改成 \(0\)。

也就是说需要维护一个数据结构支持区间修改,查询一个点右边第一个 \(0/1\),并且能查询最高位的 \(1\)。
用线段树+线段树二分维护就可以了,维护区间最小值和最大值以及区间覆盖的懒惰标记即可。

最后注意答案可能超过 \(2\times 10^5\),数组要开大一点。

int n,T,x,y,tmp,a[maxn],t[maxn],minx[maxn<<2],maxx[maxn<<2],f[maxn<<2],L,R,C;
void up(int rt){
	minx[rt]=mmin(minx[rt<<1],minx[rt<<1|1]);
	maxx[rt]=mmax(maxx[rt<<1],maxx[rt<<1|1]);
	return;
}
void down(int rt){
	if(f[rt]!=-1){
		minx[rt<<1]=maxx[rt<<1]=f[rt<<1]=f[rt];
		minx[rt<<1|1]=maxx[rt<<1|1]=f[rt<<1|1]=f[rt];
		f[rt]=-1;
	} return;
}
void build(int l,int r,int rt){
	f[rt]=-1; if(l==r){ maxx[rt]=minx[rt]=t[l]; return; } int mid=(l+r)>>1;
	build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); up(rt); return;
}
void update(int l,int r,int rt){
	if(L<=l&&r<=R){ minx[rt]=maxx[rt]=f[rt]=C; return; } int mid=(l+r)>>1; down(rt);
	if(mid>=L) update(l,mid,rt<<1); if(mid<R) update(mid+1,r,rt<<1|1); up(rt); return;
}
int query1(int l,int r,int rt){
	if(maxx[rt]==0) return INF;
	if(l==r) return l; int mid=(l+r)>>1; down(rt);
	if(mid>=L&&maxx[rt<<1]){
		int tmp=query1(l,mid,rt<<1);
		if(tmp!=INF) return tmp;
	} return query1(mid+1,r,rt<<1|1);
}
int query0(int l,int r,int rt){
	if(minx[rt]) return INF;
	if(l==r) return l; int mid=(l+r)>>1; down(rt);
	if(mid>=L&&!minx[rt<<1]){
		int tmp=query0(l,mid,rt<<1);
		if(tmp!=INF) return tmp;
	} return query0(mid+1,r,rt<<1|1);
}
int findans(int l,int r,int rt){
	if(!maxx[rt]) return -1;
	if(l==r) return l; int mid=(l+r)>>1; down(rt);
	if(maxx[rt<<1|1]) return findans(mid+1,r,rt<<1|1);
	else return findans(l,mid,rt<<1);
}
int main(){
	n=read(); T=read(); int i; for(i=1;i<=n;i++) a[i]=read(),t[a[i]]++;
	for(i=1;i<=N;i++) t[i+1]+=t[i]/2,t[i]&=1; build(1,N,1);
	while(T--){
		x=read(); y=read();
		L=a[x]; tmp=query1(1,N,1); L=R=tmp; C=0; update(1,N,1);
		if(tmp>a[x]){ L=a[x]; R=tmp-1; C=1; update(1,N,1); }
		L=y; tmp=query0(1,N,1); L=R=tmp; C=1; update(1,N,1);
		if(tmp>y){ L=y; R=tmp-1; C=0; update(1,N,1); }
		a[x]=y; print(findans(1,N,1)),pc('\n');
	} return 0;
}

标签:rt,tmp,数字,题解,Professor,mid,down,CF1705E,改成
来源: https://www.cnblogs.com/jiangtaizhe001/p/16491542.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有