zoukankan      html  css  js  c++  java
  • BZOJ4942 [Noi2017]整数

    题解:

    这题有点卡常数(自己的常数大)

    每30位压成一个数

    思路1:

    每次操作拆成最多两个位置的操作

    每加一次最多会进1

    每减一次最多会退1

    然后用线段树维护最近的非0位和非满位

    然后就是区间赋值和单点修改

    好难写没写出来QWQ

    思路2:

    分两个数组记录加操作(A)和减操作(B)

    用set维护所有的不同位置

    比较两个字符串的大小即找到第一个不同的位置

    查询时分情况讨论

    A的这一位是1还是0,B的这一位是1还是0,以及AB的后缀大小情况

    讨论进位退位即可

    暴力修改即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    using namespace std;
    const int u=30;
    const int ux=(1<<u);
    typedef long long Lint;
    const int maxn=2000009;
    
    int n;
    int TT,t1,t2,t3;
    
    Lint A[maxn]={0};
    Lint B[maxn]={0};
    
    set<int>S;
    int cmp(int x){
    	set<int>::iterator it=S.upper_bound(x);
    	if(it==S.begin())return 0;
    	--it;
    	if(A[*it]>B[*it])return 1;
    	if(A[*it]<B[*it])return -1;
    }
    
    void pushup(int bol){
    	if(A[bol]==B[bol]){
    		if(S.count(bol))S.erase(bol);
    	}
    	if(A[bol]!=B[bol]){
    		if(!S.count(bol))S.insert(bol);
    	}
    }
    
    void print(Lint x){
    	if(x==0)return;
    	print(x>>1);
    	if(x&1)printf("1");
    	else printf("0");
    }
    
    int main(){
    	scanf("%d%d%d%d",&TT,&t1,&t2,&t3);
    	n=TT+1000;
    	
    	while(TT--){
    		int opty,y;
    		Lint x;
    		scanf("%d",&opty);
    		if(opty==1){
    			scanf("%lld%d",&x,&y);
    			++y;
    			int bol=(y-1)/u+1;
    			y-=(bol-1)*u;
    			
    			if(x>0){
    				A[bol]+=(x<<(y-1));
    				while(A[bol]>=ux){
    					A[bol+1]+=A[bol]/ux;
    					A[bol]%=ux;
    					pushup(bol);
    					++bol;
    				}
    				pushup(bol);
    			}else{
    				x=-x;
    				B[bol]+=(x<<(y-1));
    				while(B[bol]>=ux){
    					B[bol+1]+=B[bol]/ux;
    					B[bol]%=ux;
    					pushup(bol);
    					++bol;
    				}
    				pushup(bol);
    			}
    		}else{
    			scanf("%d",&y);
    			++y;
    			int bol=(y-1)/u+1;
    			y-=(bol-1)*u;
    	
    			Lint tm1=A[bol]&((1<<(y-1))-1);
    			Lint tm2=B[bol]&((1<<(y-1))-1);
    			int tm3=cmp(bol-1);
    			int r=0;
    			if(tm1==tm2){
    				r=tm3;
    			}else if(tm1<tm2){
    				r=-1;
    			}else{
    				r=1;
    			}
    			if(A[bol]&(1<<(y-1))){
    				if(B[bol]&(1<<(y-1))){
    					if(r<0)printf("1
    ");
    					else printf("0
    ");
    				}else{
    					if(r>=0)printf("1
    ");
    					else printf("0
    ");
    				}
    			}else{
    				if(B[bol]&(1<<(y-1))){
    					if(r>=0)printf("1
    ");
    					else printf("0
    ");
    				}else{
    					if(r<0)printf("1
    ");
    					else printf("0
    ");
    				}
    			}
    		}
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    Oracle最大连续访问天数
    oracle中MINUS
    sql中含有中文,export oralce编码格式的环境变量
    alternate_file_dcol_rollback
    oracle查询分区表
    hive创建表sql
    使用ANSI改变终端输出样式
    Golang中的空字符,似花不是花
    程序员必看 Linux 常用命令(重要)
    MongoDB入门介绍与案例分析
  • 原文地址:https://www.cnblogs.com/zzyer/p/8560792.html
Copyright © 2011-2022 走看看