zoukankan      html  css  js  c++  java
  • UOJ#314. 【NOI2017】整数 其他

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

    题解

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

      但是有减法怎么办???

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

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

      显然关键是退不退位。

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

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

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

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

      时间复杂度 $O(nlog 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
    ",a);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    在CSS里加下面任何一行代码都可以解决图片之间的间隙
    MasterPage Toolbar
    图解虚拟机VMware服务自动启动
    WSUS完全部署
    DIV全屏覆盖网页
    大型架构.net平台篇(WEB层均衡负载nginx)
    组策略设置及导出导入方法[附上设置好的组策略]
    如何設定定時關機?
    gridview获取当前行索引的方法
    no suject
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ314.html
Copyright © 2011-2022 走看看