其他分享
首页 > 其他分享> > UOJ#314. 【NOI2017】整数 其他

UOJ#314. 【NOI2017】整数 其他

作者:互联网

原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ314.html

题解

  如果只加不减,那么瞎势能分析一波可以知道暴力模拟的复杂度是对的。

  但是有减法怎么办???

  再搞一个类似的,维护减了多少。

  那么,询问一个数位的值的时候,我们只需要得到两部分值中这一位的值是多少,以及是否退位,就可以得到答案。

  显然关键是退不退位。

  退不退位看这一位之后的后缀部分哪一个大。

  这里我们需要这样做: 如果加法和减法两部分维护的值中,某一位都不是 0 ,那么就两边互相抵消,直到两边至少有一个是 0 。

  那么判断哪一个大就是看两部分中,当前位以后,第一个有值的位置是哪一个大。用两个set瞎搞就好了。

  我们维护的时候用 $2^{30}$ 进制,这样时间复杂度就可以接受了。

  时间复杂度 $O(n\log n)$ 。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define y1 __zzd001
using namespace std;
typedef long long LL;
LL read(){
	LL x=0,f=0;
	char ch=getchar();
	while (!isdigit(ch))
		f|=ch=='-',ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
const int N=(1<<20)+5;
int n,t1,t2,t3,base=1<<30;
int v[2][N];
set <int> s[2];
void upd1(int a,int b){
	if (!a)
		return;
	if (v[1][b]){
		int d=min(v[1][b],a);
		v[1][b]-=d,a-=d;
		if (!v[1][b])
			s[1].erase(b);
	}
	if (!a)
		return;
	if (!v[0][b])
		s[0].insert(b);
	v[0][b]+=a;
	if (v[0][b]>=base){
		if (!(v[0][b]-=base))
			s[0].erase(b);
		upd1(1,b+1);
	}
}
void upd2(int a,int b){
	if (!a)
		return;
	if (v[0][b]){
		int d=min(v[0][b],a);
		v[0][b]-=d,a-=d;
		if (!v[0][b])
			s[0].erase(b);
	}
	if (!a)
		return;
	if (!v[1][b])
		s[1].insert(b);
	v[1][b]+=a;
	if (v[1][b]>=base){
		if (!(v[1][b]-=base))
			s[1].erase(b);
		upd2(1,b+1);
	}
}
int main(){
	n=read(),t1=read(),t2=read(),t3=read();
	clr(v);
	s[0].clear(),s[1].clear();
	s[0].insert(-1),s[1].insert(-1);
	while (n--){
		int type=read();
		if (type==1){
			int a=read(),b=read();
			int c=b%30,d=b/30;
			if (a>=0){
				upd1((a<<c)&(base-1),d);
				upd1(a>>(30-c),d+1);
			}
			else {
				a=-a;
				upd2((a<<c)&(base-1),d);
				upd2(a>>(30-c),d+1);
			}
		}
		else {
			int k=read();
			int a=(v[0][k/30]>>(k%30)&1)^(v[1][k/30]>>(k%30)&1);
			int x=v[0][k/30]&((1<<(k%30))-1);
			int y=v[1][k/30]&((1<<(k%30))-1);
			if (x!=y){
				if (x<y)
					a^=1;
			}
			else if (*--s[0].lower_bound(k/30)<*--s[1].lower_bound(k/30))
				a^=1;
			printf("%d\n",a);
		}
	}
	return 0;
}

  

标签:insert,ch,return,int,30,314,read,NOI2017,UOJ
来源: https://www.cnblogs.com/zhouzhendong/p/UOJ314.html