zoukankan      html  css  js  c++  java
  • [bzoj4942][noi2017]整数【线段树】

    【题目描述】

     http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf

    【题解】

     每个操作若不要进退位就暴力修改,否则用线段树找到下一个可以进退位的地方,并将中间部分翻转(0变为1,1变为0)

    把30个二进制位压在一起存储,这样修改时最多进退位2次。复杂度 O(n log n).

    /* --------------
        user Vanisher
        problem bzoj-4942 
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	N 		1000100
    # define 	inf 	(1<<30)
    using namespace std;
    int read(){
    	int tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    struct Tree{
    	int pl,pr,l,r,tag,num0,num1;
    }T[N*3];
    int now[N],n,place,rt;
    int build(int l, int r){
    	int p=++place;
    	T[p].l=l; T[p].r=r;
    	T[p].num0=0; T[p].num1=r-l+1;
    	if (l!=r){
    		int mid=(l+r)/2;
    		T[p].pl=build(l,mid);
    		T[p].pr=build(mid+1,r);
    	}
    	return p;
    }
    void pushtag(int p){
    	if (T[p].tag%2!=0){
    		swap(T[p].num0,T[p].num1);
    		if (T[p].l!=T[p].r) T[T[p].pl].tag++, T[T[p].pr].tag++;
    			else now[T[p].l]=inf-1-now[T[p].l];
    	}
    	T[p].tag=0;
    }
    void reser(int p, int l, int r){
    	pushtag(p);
    	if (T[p].l==l&&T[p].r==r){
    		T[p].tag++; return;
    	}
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid>=r) reser(T[p].pl,l,r);
    		else if (mid<l) reser(T[p].pr,l,r);
    			else {
    				reser(T[p].pl,l,mid);
    				reser(T[p].pr,mid+1,r);
    			}
    	pushtag(T[p].pl); pushtag(T[p].pr);
    	T[p].num0=T[T[p].pl].num0+T[T[p].pr].num0;
    	T[p].num1=T[T[p].pl].num1+T[T[p].pr].num1;
    }
    void join1(int p, int x){
    	pushtag(p); T[p].num1--;
    	if (T[p].l!=T[p].r){
    		int mid=(T[p].l+T[p].r)/2;
    		if (mid>=x) join1(T[p].pl,x); else join1(T[p].pr,x);
    	}
    }
    void join0(int p, int x){
    	pushtag(p); T[p].num0--;
    	if (T[p].l!=T[p].r){
    		int mid=(T[p].l+T[p].r)/2;
    		if (mid>=x) join0(T[p].pl,x); else join0(T[p].pr,x);
    	}
    }
    void del1(int p, int x){
    	pushtag(p); T[p].num1++;
    	if (T[p].l!=T[p].r){
    		int mid=(T[p].l+T[p].r)/2;
    		if (mid>=x) del1(T[p].pl,x); else del1(T[p].pr,x);
    	}
    }
    void del0(int p, int x){
    	pushtag(p); T[p].num0++;
    	if (T[p].l!=T[p].r){
    		int mid=(T[p].l+T[p].r)/2;
    		if (mid>=x) del0(T[p].pl,x); else del0(T[p].pr,x);
    	}
    }
    void getdown(int p, int x){
    	pushtag(p);
    	if (T[p].l==T[p].r) return;
    	int mid=(T[p].l+T[p].r)/2;
    	if (x<=mid) getdown(T[p].pl,x);
    		else getdown(T[p].pr,x);
    }
    int findnex0(int p, int l){
    	pushtag(p);
    	if (T[p].num0==0) return -1;
    	if (T[p].l==T[p].r&&T[p].num0==1) return T[p].l;
    	int mid=(T[p].l+T[p].r)/2,k;
    	if (T[p].l<=l){
    		if (l<=mid){
    			k=findnex0(T[p].pl,l);
    			if (k!=-1) return k;
    			return findnex0(T[p].pr,l);
    		}
    		else return findnex0(T[p].pr,l);
    	}
    	else {
    		pushtag(T[p].pl); pushtag(T[p].pr);
    		if (T[T[p].pl].num0!=0)
    			return findnex0(T[p].pl,l);
    				else return findnex0(T[p].pr,l);
    	}
    }
    int findnex1(int p, int l){
    	pushtag(p);
    	if (T[p].num1==0) return -1;
    	if (T[p].l==T[p].r&&T[p].num1==1) return T[p].l;
    	int mid=(T[p].l+T[p].r)/2,k;
    	if (T[p].l<=l){
    		if (l<=mid){
    			k=findnex1(T[p].pl,l);
    			if (k!=-1) return k;
    			return findnex1(T[p].pr,l);
    		}
    		else return findnex1(T[p].pr,l);
    	}
    	else {
    		pushtag(T[p].pl); pushtag(T[p].pr);
    		if (T[T[p].pl].num1!=0)
    			return findnex1(T[p].pl,l);
    				else return findnex1(T[p].pr,l);
    	}
    }
    void modify(int p, int num){
    	if (num==0) return;
    	getdown(rt,p);
    	if (now[p]==inf-1) del1(rt,p);
    	if (now[p]==0) del0(rt,p);
    	now[p]=now[p]+num;
    	if (now[p]>=inf) {
    		now[p]=now[p]-inf;
    		int nex=findnex1(rt,p+1);
    		if (p+1<=nex-1) reser(rt,p+1,nex-1);
    		modify(nex,1);
    	}
    	if (now[p]<0) {
    		now[p]=now[p]+inf;
    		int nex=findnex0(rt,p+1);
    		if (p+1<=nex-1) reser(rt,p+1,nex-1);
    		modify(nex,-1);
    	}
    	if (now[p]==inf-1) join1(rt,p);
    	if (now[p]==0) join0(rt,p);
    }
    int main(){
    	n=read(); 
    	int t1=read(), t2=read(), t3=read(),tmp1,tmp2,a,b,opt,fh;
    	rt=build(0,n);
    	for (int i=1; i<=n; i++){
    		opt=read();
    		if (opt==1){
    			a=read(), b=read();
    			if (a<0) fh=-1,a=-a; else fh=1;
    			tmp1=(a%(1<<(30-b%30)))<<(b%30);
    			tmp2=a>>(30-b%30); 
    			modify(b/30,tmp1*fh); modify(b/30+1,tmp2*fh);
    		}
    		else {
    			a=read();
    			getdown(rt,a/30);
    			if ((now[a/30]&(1<<(a%30)))==0)
    				printf("0
    ");
    				else printf("1
    ");	
    		}
    	}
    	return 0;
    }
    


  • 相关阅读:
    如何使用 @ OutputCache 指令的 VaryByCustom 属性来缓存不同版本的页面
    看不懂 ASP.NET 相册上传代码
    asp.net判断是1.1还是2.0主要由Code*属性来解决,判断规则如下:
    引号看不懂
    GridView的行删除事件 //取当前行的Id
    <Columns></Columns>中间的是列集合
    DropDownList1.SelectedIndex = 0 DropDownList1处于位选择任何选项的状态下
    是一个查询语句 查询ZhuanJia表里面id=输入id的数据
    验证码图片的解释
    get和post区别:
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136026.html
Copyright © 2011-2022 走看看