LOJ#2302. 「NOI2017」整数

$n \leq 1000000$个操作:一,给$x$加上$a*2^b$;二,问$x$的某个二进制位$k$。$b,k \leq 30n$,$|a| \leq 1e9$。

30暴露了一切。。可以把30个二进制位压一位,进位用线段树找到第一个0,而退位用类似的方法找到第一个1。

但其实第$k$位只由加的总量和减的总量的0到$k$这些数位上决定。因此可以把加减分成两个数组,不用再写一个线段树里的减法。回答时查一下$0$到$k-1$中加的和减的孰大孰小,以及第$k$位是否相同,分类可得答案。

这里写的直接模拟。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<math.h>
  5 //#include<set>
  6 //#include<queue>
  7 //#include<bitset>
  8 //#include<vector>
  9 #include<algorithm>
 10 #include<stdlib.h>
 11 using namespace std;
 12 
 13 #define LL long long
 14 int qread()
 15 {
 16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
 17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
 18 }
 19 
 20 //Pay attention to '-' , LL and double of qread!!!!
 21 
 22 int m,n;
 23 #define maxn 1000011
 24 int pos[maxn];
 25 struct SMT
 26 {
 27     struct Node{int ls,rs,v; bool all0,all1,be0,be1;}a[maxn<<1];
 28     int size,n;
 29     void up(int x)
 30     {a[x].all0=a[a[x].ls].all0&a[a[x].rs].all0; a[x].all1=a[a[x].ls].all1&a[a[x].rs].all1;}
 31     void build(int &x,int L,int R)
 32     {
 33         x=++size;
 34         a[x].all0=1; a[x].all1=a[x].be0=a[x].be1=0;
 35         if (L==R) {a[x].v=0; pos[L]=x; return;}
 36         int mid=(L+R)>>1;
 37         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R);
 38     }
 39     void clear(int N) {n=N; size=0; int x; build(x,1,n);}
 40     
 41     void besingle(int x,bool t)
 42     {
 43         a[x].all0=a[x].be0=!t;
 44         a[x].all1=a[x].be1=t;
 45         if (t) a[x].v=(1<<30)-1; else a[x].v=0;
 46     }
 47     void down(int x)
 48     {
 49         Node &b=a[x];
 50         if (b.be0) {besingle(b.ls,0); besingle(b.rs,0); b.be0=0;}
 51         if (b.be1) {besingle(b.ls,1); besingle(b.rs,1); b.be1=0;}
 52     }
 53     
 54     bool Add(int x,int L,int R,int p,int v)
 55     {
 56         if (L==R)
 57         {
 58             a[x].v+=v; if (a[x].v>=(1<<30))
 59             {
 60                 a[x].v^=(1<<30);
 61                 a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
 62                 return 1;
 63             }
 64             a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
 65             return 0;
 66         }
 67         down(x);
 68         int mid=(L+R)>>1;
 69         if (p<=mid) {bool flag=Add(a[x].ls,L,mid,p,v); up(x); return flag;}
 70         bool flag=Add(a[x].rs,mid+1,R,p,v); up(x); return flag;
 71     }
 72     bool f0(int x,int L,int R,int p)
 73     {
 74         if (L==R)
 75         {
 76             bool flag=0;
 77             for (int i=0;i<30;i++) if (((a[x].v>>i)&1)==0) {a[x].v|=1<<i; flag=1; break;}
 78             else a[x].v^=(1<<i);
 79             a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
 80             return flag;
 81         }
 82         down(x);
 83         int mid=(L+R)>>1;
 84         if (L>p)
 85         {
 86             if (a[x].all1) {besingle(x,0); return 0;}
 87             if (!f0(a[x].ls,L,mid,p)) f0(a[x].rs,mid+1,R,p); up(x);
 88             return 1;
 89         }
 90         if (mid>p)
 91         {
 92             if (f0(a[x].ls,L,mid,p)) {up(x); return 1;}
 93             bool flag=f0(a[x].rs,mid+1,R,p); up(x); return flag;
 94         }
 95         if (f0(a[x].rs,mid+1,R,p)) {up(x); return 1;}
 96         up(x); return 0;
 97     }
 98     void add(int p,int v) {p++; if (Add(1,1,n,p,v) && p!=n) f0(1,1,n,p);}
 99     
100     bool Minus(int x,int L,int R,int p,int v)
101     {
102         if (L==R)
103         {
104             a[x].v-=v; if (a[x].v<0)
105             {
106                 a[x].v+=(1<<30);
107                 a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
108                 return 1;
109             }
110             a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
111             return 0;
112         }
113         down(x);
114         int mid=(L+R)>>1;
115         if (p<=mid) {bool flag=Minus(a[x].ls,L,mid,p,v); up(x); return flag;}
116         bool flag=Minus(a[x].rs,mid+1,R,p,v); up(x); return flag;
117     }
118     bool f1(int x,int L,int R,int p)
119     {
120         if (L==R)
121         {
122             bool flag=0;
123             for (int i=0;i<30;i++) if (((a[x].v>>i)&1)==1) {a[x].v^=1<<i; flag=1; break;}
124             else a[x].v^=(1<<i);
125             a[x].all0=(a[x].v==0),a[x].all1=(a[x].v==(1<<30)-1);
126             return flag;
127         }
128         down(x);
129         int mid=(L+R)>>1;
130         if (L>p)
131         {
132             if (a[x].all0) {besingle(x,1); return 0;}
133             if (!f1(a[x].ls,L,mid,p)) f1(a[x].rs,mid+1,R,p);
134             up(x); return 1;
135         }
136         if (mid>p)
137         {
138             if (f1(a[x].ls,L,mid,p)) {up(x); return 1;}
139             bool flag=f1(a[x].rs,mid+1,R,p); up(x); return flag;
140         }
141         if (f1(a[x].rs,mid+1,R,p)) {up(x); return 1;}
142         up(x); return 0;
143     }
144     void minus(int p,int v) {p++; if (Minus(1,1,n,p,v) && p!=n) f1(1,1,n,p);}
145     
146     int Query(int x,int L,int R,int p,int v)
147     {
148         if (L==R) return (a[x].v>>v)&1;
149         down(x);
150         int mid=(L+R)>>1;
151         if (p<=mid) return Query(a[x].ls,L,mid,p,v);
152         return Query(a[x].rs,mid+1,R,p,v);
153     }
154     int query(int x) {return Query(1,1,n,x/30+1,x%30);}
155 }t;
156 
157 int main()
158 {
159     m=qread(); n=qread(); n=qread(); n=qread();
160     n=1000000;
161     t.clear(n);
162     
163     int op,x,y;
164     while (m--)
165     {
166         op=qread();
167         if (op==1)
168         {
169             x=qread(); y=qread();
170             if (x>0)
171             {
172                 int p=y/30,q=(p+1)*30-y;
173                 int a=x&((1<<q)-1),b=x>>q; a<<=y-p*30;
174                 t.add(p,a); if (b) t.add(p+1,b);
175             }
176             else
177             {
178                 x=-x;
179                 int p=y/30,q=(p+1)*30-y;
180                 int a=x&((1<<q)-1),b=x>>q; a<<=y-p*30;
181                 t.minus(p,a); if (b) t.minus(p+1,b);
182             }
183         }
184         else
185         {
186             x=qread();
187             printf("%d\n",t.query(x));
188         }
189     }
190     return 0;
191 }
View Code

 

posted @ 2018-06-20 18:56  Blue233333  阅读(271)  评论(0编辑  收藏  举报