1. 程式人生 > >LOJ#2302. 「NOI2017」整數

LOJ#2302. 「NOI2017」整數

names 是否 因此 直接 二進制 += -- TE 技術

$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

LOJ#2302. 「NOI2017」整數