[树状数组]操作数列

来源:互联网 发布:犀牛软件6.0下载 编辑:程序博客网 时间:2024/05/14 02:24

Problem E: 操作数列

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 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****************************************************************/


0 0
原创粉丝点击