4942: [Noi2017]整数
Time Limit: 50 Sec Memory Limit: 512 MB
Submit: 363 Solved: 237
[Submit][Status][Discuss]
Description
http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf
Input
Output
Sample Input
Sample Output
HINT
分析:
如果维护一个3*10^7次方的数组表示这个数,只有加法是很好办的,但是有减法的话就不好办了。所以维护两个3*10^7次方的数组,表示加法每一位是否是1减法每一位是否是1.
查询的时候高位是不关乎当前位的事,只关心当前位的加减法和低位中最高位加减法数组不同的两个位置,加减法不同的位置可以用线段树维护。
AC代码:
# include <iostream> # include <cstdio> using namespace std; const int N = 1 << 26; const int mx = 1 << 25; bool Inc[N],Dec[N],t[N << 1]; int l,r,n; int read() { int x = 0,f = 1;char i = getchar(); while(!isdigit(i))f = i == '-' ? -1 : f,i = getchar(); while(isdigit(i))x = x * 10 + i - '0',i = getchar(); return x * f; } void add(bool *c,int x) { for(;c[x];c[x++] = 0); c[x] = 1; if(x > r)r = x; } int find(int x) { for(x += mx;x;x >>= 1)if(x & 1 & t[x ^ 1]) { for(x ^= 1;x < mx;x = x << 1 ^ t[x << 1 | 1]); return x - mx; } return -1; } int main() { int tp,x,y;n = read();read();read();read(); while(n--) { tp = read(); if(tp & 1) { x = read();y = read(); if(!x)continue; l = r = y;tp = x > 0 ? 1 : 0;x = x > 0 ? x : -x; if(tp){for(int i = 0;i < 30;i++)if(x >> i & 1)add(Inc,y + i);} else {for(int i = 0;i < 30;i++)if(x >> i & 1)add(Dec,y + i);} for(int i = l;i <= r;i++)t[i + mx] = Inc[i] ^ Dec[i]; for(l = (l + mx) >> 1,r = (r + mx) >> 1;l;l >>= 1,r >>= 1) for(int i = l;i <= r;i++)t[i] = t[i << 1] | t[i << 1 | 1]; } else { x = read();y = find(x); printf("%d\n",t[x + mx] ^ (~y && Inc[y] < Dec[y]) ? 1 : 0); } } }