BZOJ4942【noi2017】整数

luogu的题面

https://www.luogu.org/problemnew/show/P3822

题意:
     x初始为0,维护+a*2^k ,其中a为整数,k为自然数;查询x的第k位;

题解:
    ①将数看成序列,线段树逐位维护。比较大,压位(下面的代码base=30,ls()
rs()为左右儿子)。

    ②输入1,a,b,即将b/base号节点加 (a<<b%base)的base位以内部分,b/base+1号节点加 (a<<b%base)base位以上的部分。

    ③假设我们已经找到了b对应的叶子节点,修改后考虑进位。定义fg1[k]表示k节点是否是最大值(1<<base)-1,b对应的叶子往上跳一层到k号节点,如果fg1[rs(k)]==false,直接rs(k)里进位就好了,否则把rs(k)清零,再往上跳,退位同理(写的时候记得pushdown和pushup 。。。。TAT);

 

  1 #pragma GCC optimize(2)
  2 #include<cstdio>
  3 #include<iostream>
  4 //#define N 1000100
  5 //#define base 30
  6 #define ll long long
  7 #define ls(k) (k<<1)
  8 #define rs(k) (ls(k)|1) 
  9 using namespace std;
 10 const ll base=30,N=4.2e7/base,B=(1<<base)-1,len=4.1e7/base;
 11 //const int B = (1<<base) - 1,len = 1e6 + 5;
 12 int n,t1,t2,t3;
 13 int w[N<<2],fg1[N<<2],fg0[N<<2],ly1[N<<2],ly0[N<<2];
 14 char gc(){
 15     static char *p1,*p2,s[1000000];
 16     if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin);
 17     return(p1==p2)?EOF:*p1++;
 18 }
 19 int rd(){
 20     int x = 0,f = 1; char c = gc();
 21     while(c<'0'||c>'9') {if(c=='-') f = -1; c = gc();}
 22     while(c>='0'&&c<='9') {x = x * 10 + c - '0'; c = gc();}
 23     return x * f;
 24 }
 25 void pushup(int k){
 26     int l = ls(k),r = rs(k);
 27     fg0[k] = fg0[l] && fg0[r];
 28     fg1[k] = fg1[l] && fg1[r];
 29 }
 30 void mdf(int k,int typ){
 31     w[k] = B * typ;
 32     fg1[k] = ly1[k] = typ; 
 33     fg0[k] = ly0[k] = !typ;
 34 }
 35 void pushdown(int k){
 36     int l = ls(k),r = rs(k);
 37     if(ly0[k]) mdf(l,0),mdf(r,0),ly0[k] = 0;
 38     if(ly1[k]) mdf(l,1),mdf(r,1),ly1[k] = 0;    
 39 }
 40 void change(int k,int l,int r,int typ){
 41     if(l==r) {
 42         w[k]+=typ;
 43         fg0[k]  = !w[k];
 44         fg1[k]  = (w[k]==B);
 45     }
 46     else{
 47         if(ly0[k]||ly1[k]) pushdown(k); 
 48         int mid = (l+r)>>1;
 49         if(typ==1){
 50             if(!fg1[ls(k)]) change(ls(k),l,mid,1); 
 51             else mdf(ls(k),0),change(rs(k),mid+1,r,1);
 52         }
 53         else{
 54             if(!fg0[ls(k)]) change(ls(k),l,mid,-1);
 55             else mdf(ls(k),1),change(rs(k),mid+1,r,-1);
 56         }
 57         pushup(k);
 58     }
 59 }
 60 int update(int k,int l,int r,int x,int y){
 61     if(!y) return 0;
 62     int typ = 0;
 63     if(l==r) {
 64         w[k] += y;
 65         if(w[k]>=(1<<base)) w[k] -= (1<<base),typ = 1;
 66         else if(w[k]<0) w[k] += (1<<base),typ = -1;
 67         fg0[k]  = !w[k];
 68         fg1[k]  = (w[k]==B);
 69     }
 70     else {
 71         if(ly0[k]||ly1[k]) pushdown(k);
 72         int mid = (l + r)>>1;
 73         if(x<=mid){
 74             typ = update(ls(k),l,mid,x,y);
 75             if(typ==1) {
 76                 if(!fg1[rs(k)]) typ = 0,change(rs(k),mid+1,r,1);
 77                 else mdf(rs(k),0);
 78             }
 79             if(typ==-1){
 80                 if(!fg0[rs(k)]) typ = 0,change(rs(k),mid+1,r,-1);
 81                 else mdf(rs(k),1);
 82             }
 83         }
 84         else typ = update(rs(k),mid+1,r,x,y);
 85         pushup(k);
 86     }
 87     return typ;
 88 }
 89 int query(int k,int l,int r,int x,int y){
 90     if(l==r) return bool(w[k]&y);
 91     else {
 92         if(ly0[k]||ly1[k]) pushdown(k);
 93         int mid = (l + r)>>1;
 94         if(x<=mid) return query(ls(k),l,mid,x,y);
 95         else return query(rs(k),mid+1,r,x,y);
 96     }
 97 }
 98 int main()
 99 {    //freopen("mzoj1111.in","r",stdin);
100     //freopen("mzoj1111.out","w",stdout);
101     n = rd(); t1 = rd(); t2 = rd(); t3 = rd();
102     fg0[1] = ly0[1] = 1;
103     for(int i = 1;i <= n;i++){
104         ll opt = rd(),f,a,b,x,y;
105         if(opt&1){
106             a = rd(); b = rd();
107             if(a<0) a*=-1,f=-1; else f=1;
108             a <<= (b%base); b /= base;
109             update(1,0,len,b,f*(a&B));
110             update(1,0,len,b+1,f*(a>>base));
111         }
112         else{
113             x = rd();
114             y = 1<<(x%base); x /= base; 
115             int ans = query(1,0,len,x,y);
116             printf("%d\n",ans);
117         }
118     }
119     return 0;
120 }//by tkys_Austin;

 

 

 

posted @ 2018-03-16 11:57  大米饼  阅读(478)  评论(0编辑  收藏  举报