[CodeForces242E]XOR on Segment-线段树

来源:互联网 发布:在java当中interface 编辑:程序博客网 时间:2024/06/07 01:01

XOR on Segment

You’ve got an array a, consisting of n integers a1, a2, …, an. You are allowed to perform two operations on this array:

Calculate the sum of current array elements on the segment [l, r], that is, count value al + al + 1 + … + ar.
Apply the xor operation with a given number x to each array element on the segment [l, r], that is, execute . This operation changes exactly r - l + 1 array elements.
Expression means applying bitwise xor operation to numbers x and y. The given operation exists in all modern programming languages, for example in language C++ and Java it is marked as “^”, in Pascal — as “xor”.

You’ve got a list of m operations of the indicated type. Your task is to perform all given operations, for each sum query you should print the result you get.

Input

The first line contains integer n (1 ≤ n ≤ 105) — the size of the array. The second line contains space-separated integers a1, a2, …, an (0 ≤ ai ≤ 106) — the original array.

The third line contains integer m (1 ≤ m ≤ 5·104) — the number of operations with the array. The i-th of the following m lines first contains an integer ti (1 ≤ ti ≤ 2) — the type of the i-th query. If ti = 1, then this is the query of the sum, if ti = 2, then this is the query to change array elements. If the i-th operation is of type 1, then next follow two integers li, ri (1 ≤ li ≤ ri ≤ n). If the i-th operation is of type 2, then next follow three integers li, ri, xi (1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 106). The numbers on the lines are separated by single spaces.

Output

For each query of type 1 print in a single line the sum of numbers on the given segment. Print the answers to the queries in the order in which the queries go in the input.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams, or the %I64d specifier.

Examples

input

54 10 3 13 781 2 42 1 3 31 2 41 3 32 2 5 51 1 52 1 2 101 2 3

output

262203411

input

64 7 4 0 7 352 2 3 81 1 52 3 5 12 4 5 61 2 3

output

3828

水题一眼切……
然而调tag调了半天……

(╯‵□′)╯︵┻━┻


题意:
维护一个数据结构,支持两个操作:
1 l r :输出[l,r]区间的和
2 l r x :将[l,r]区间的数异或上x

思路:
看到异或显然是要拆位了~
然后显然是要用线段树。
在每个节点维护一个桶,分别存每个二进制位的0和1分别出现了多少个即可~
异或操作相当于打个tag,将对应有1的二进制位处的0和1的个数交换即可~

是不是很水然而咱就是调了将近1h.jpg

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;const int N=1e5+9;struct node{    int bit[22][2];    node(){memset(bit,0,sizeof(bit));}    inline void operator = (int x)    {        for(int i=20;i>=0;i--)            bit[i][(x>>i)&1]++;    }    inline ll get()    {        ll ans=0;        for(int i=20;i>=0;i--)            ans=(ans<<1)+(ll)bit[i][1];        return ans;    }    inline node operator + (node o)    {        node ret;        for(int i=20;i>=0;i--)        {            ret.bit[i][0]=bit[i][0]+o.bit[i][0];            ret.bit[i][1]=bit[i][1]+o.bit[i][1];        }        return ret;    }};node t[N<<2];int n,m,tag[N<<2],a[N];inline int read(){    int x=0;char ch=getchar();    while(ch<'0' || '9'<ch)ch=getchar();    while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();    return x;}inline void flush(int x,int val){    for(int i=20;i>=0;i--)        if((val>>i)&1)            swap(t[x].bit[i][0],t[x].bit[i][1]);}inline void push(int x,int l,int r){    if(l==r)    {        tag[x]=0;        return;    }    if(tag[x])    {        int mid=l+r>>1;        flush(x<<1,tag[x]);        flush(x<<1|1,tag[x]);        tag[x<<1]^=tag[x];        tag[x<<1|1]^=tag[x];        tag[x]=0;    }}inline void update(int x){    t[x]=t[x<<1]+t[x<<1|1];}void build(int x,int l,int r){    tag[x]=0;    if(l==r)    {        t[x]=a[l]=read();        return;    }    int mid=l+r>>1;    build(x<<1,l,mid);    build(x<<1|1,mid+1,r);    update(x);}void modify(int x,int l,int r,int dl,int dr,int val){    push(x,l,r);    if(l==dl && r==dr)    {        tag[x]^=val;        flush(x,tag[x]);        return;    }    int mid=l+r>>1;    if(dr<=mid)        modify(x<<1,l,mid,dl,dr,val);    else if(mid<dl)        modify(x<<1|1,mid+1,r,dl,dr,val);    else    {        modify(x<<1,l,mid,dl,mid,val);        modify(x<<1|1,mid+1,r,mid+1,dr,val);    }    update(x);}ll query(int x,int l,int r,int dl,int dr){    push(x,l,r);    if(l==dl && r==dr)        return t[x].get();    int mid=l+r>>1;    if(dr<=mid)        return query(x<<1,l,mid,dl,dr);    if(mid<dl)        return query(x<<1|1,mid+1,r,dl,dr);    return query(x<<1,l,mid,dl,mid)+query(x<<1|1,mid+1,r,mid+1,dr);}int main(){    n=read();    build(1,1,n);    m=read();    for(int i=1,op,l,r;i<=m;i++)    {        op=read();        l=read();        r=read();        if(op==1)            printf("%I64d\n",query(1,1,n,l,r));        else            modify(1,1,n,l,r,read());    }    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果耳机进水后声音变了怎么办 华为荣耀开了数据用不了怎么办 华为手机高德地图信号弱怎么办? 手机QQ浏览器看视频有广告怎么办 手机显示网络连接但不可上网怎么办 华为手机关机后开不了机怎么办 华为畅享8p相机拍照模糊怎么办 手机触屏不准怎么办荣耀青春版九 华为手机锁屏手势密码忘了怎么办 荣耀手机锁屏密码忘了怎么办 华为p20隐私空间密码忘了怎么办 安全管家隐私保护的密码忘了怎么办 华为手机自带截图键删除了怎么办 飞科电吹风吹一会就断电怎么办 住酒店时电吹风吹坏了怎么办 把话费充到停机的号码上去了怎么办 电信手机卡充值了还停机怎么办 电信手机一直没用却欠费了怎么办 苹果se开起4g信号不好怎么办 触屏华为手机充不了电怎么办 华为手机自拍出来的字反向怎么办 华为微信隐藏了怎么弄出来怎么办 酷派手机酷管家密码忘了怎么办 手机磁盘目录不具有读写权限怎么办 魅族手机像素突然变模糊了怎么办 手机忽然所有软件都没了怎么办 魅族读书下架的书怎么办 我的电信大王卡激活了没信号怎么办 三星翻盖手机忘记锁屏密码怎么办 小米2s电信版信号不好怎么办 4s微信版本过低怎么办 换了一个城市牵的电信网线怎么办 联通电话卡注销了里面的钱怎么办 红米4a上网太慢怎么办 华为光猫网线接囗接触不良怎么办? 苹果电信4g信号变3g怎么办 苹果7的4g变3g了怎么办 华为路由器的登录密码忘记了怎么办 华为手机有4g但不能上网怎么办 移动4g 手机开密码忘了怎么办 华为安卓8.0屏幕上圆怎么办