Problem E: 操作数列
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 39 Solved: 10
[ Submit][ Status][ Web Board]
Description
对于一个长度为n(n<=200000)的数列。最开始,数列中的全部数都是0,然后定义如下两个操作:
1 x y c (0< x <= y <= 200000, c < 2147483645)
2 x (0 < x <= 200000)
1 x y c 操作表示,将区间[x,y]中的全部元素都异或c;
2 x 操作表示,将第x个元素输出。
Input
第一行一个 t ,表示case数;
对于每个case,第一行一个n (n <= 200000),表示数列大小;
第二行一个数 q (q <= 100000),表示接下来有q次操作;
接下来q行,每行按描述中给出一个操作。
Output
对于每个 2 x 操作,输出该操作的结果,每两个case间有一个换行。
Sample Input
21041 1 5 11 3 5 12 12 5541 1 4 12 11 1 4 22 1
Sample Output
1013
HINT
操作都用异或。
考虑到异或具有两次异或等于不异或的性质。
我们可以使用前缀的方法。
修改区间查询点和修改点查询区间是两个相反的过程。
#include <cstdio>
#include <cstring>
#define lowbit(x) ((x)&(-(x)))
int n;
const int maxn = 200010;
int tree[maxn];
void modify(int l,int c)
{
while (l >= 1)
{
tree[l] ^= c;
l -= lowbit(l);
}
}
int query(int l)
{
int ans = 0;
while (l <= n)
{
ans ^= tree[l];
l += lowbit(l);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(tree,0,sizeof tree);
int q;
scanf("%d%d",&n,&q);
while (q--)
{
int o;
scanf("%d",&o);
if (o == 1)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
modify(y,c);
modify(x-1,c);
}
else
{
int x;
scanf("%d",&x);
printf("%d\n",query(x));
}
}
printf("\n");
}
return 0;
}
/**************************************************************
Problem: 1263
User: wuyihao
Language: C++
Result: Accepted
Time:599 ms
Memory:1836 kb
****************************************************************/