[CF242E]XOR on Segment

来源:互联网 发布:js什么是实例化对象 编辑:程序博客网 时间:2024/05/17 06:16

242E:XOR on Segment

题意简述

维护一个长度为n的数列,完成q个操作,操作有两种:
1.询问[l,r]的区间和。
2.将[l,r]之间的所有数都异或val

数据范围

1n105
1q5104
1ai106

思路

线段树维护二进制每一位的个数。
异或操作对某一位来说就是交换它的0,1的个数。
维护一个lazy标记。
求和操作就把每一位的贡献合起来。
时间复杂度O(nlognlog106)

代码

#include<cstdio>#include<iostream>using namespace std;int n,q,u,v,w,opt;int seq[100010];namespace Segtree{    struct Node{        int num[20][2];        int xx;    }tree[400010];    void pushup(int node)    {        for (int i=0;i<20;i++)        {            tree[node].num[i][0]=tree[node<<1].num[i][0]+tree[node<<1|1].num[i][0];            tree[node].num[i][1]=tree[node<<1].num[i][1]+tree[node<<1|1].num[i][1];        }    }    void pushdown(int node)    {        if (tree[node].xx)        {            for (int i=0;i<20;i++)                if (tree[node].xx&(1<<i))                {                    swap(tree[node<<1].num[i][0],tree[node<<1].num[i][1]);                    swap(tree[node<<1|1].num[i][0],tree[node<<1|1].num[i][1]);                }            tree[node<<1].xx^=tree[node].xx;            tree[node<<1|1].xx^=tree[node].xx;            tree[node].xx=0;        }    }    void modify(int L,int R,int l,int r,int node,int val)    {        if (L<=l&&r<=R)        {            for (int i=0;i<20;i++)                if (val&(1<<i))                    swap(tree[node].num[i][0],tree[node].num[i][1]);            tree[node].xx^=val;            return;        }        pushdown(node);        int mid=(l+r)>>1;        if (L<=mid)            modify(L,R,l,mid,node<<1,val);        if (R>mid)            modify(L,R,mid+1,r,node<<1|1,val);        pushup(node);    }    long long query(int L,int R,int l,int r,int node)    {        if (L<=l&&r<=R)        {            long long ret=0;            for (int i=0;i<20;i++)                ret+=(1LL<<i)*tree[node].num[i][1];            return ret;        }        pushdown(node);        long long ret=0;        int mid=(l+r)>>1;        if (L<=mid)            ret+=query(L,R,l,mid,node<<1);        if (R>mid)            ret+=query(L,R,mid+1,r,node<<1|1);        return ret;    }    void build(int l,int r,int node)    {        if (l==r)        {            for (int i=0;i<20;i++)                if (seq[l]&(1<<i))                    tree[node].num[i][1]++;                else                    tree[node].num[i][0]++;            return;        }        int mid=(l+r)>>1;        build(l,mid,node<<1);        build(mid+1,r,node<<1|1);        pushup(node);    }}void init(){    scanf("%d",&n);    for (int i=1;i<=n;i++)        scanf("%d",&seq[i]);    Segtree::build(1,n,1);}void work(){    scanf("%d",&q);    for (int i=1;i<=q;i++)    {        scanf("%d",&opt);        if (opt==1)        {            scanf("%d%d",&u,&v);            printf("%I64d\n",Segtree::query(u,v,1,n,1));        }        if (opt==2)        {            scanf("%d%d%d",&u,&v,&w);            Segtree::modify(u,v,1,n,1,w);        }    }}int main(){    init();    work();    return 0;}
0 0
原创粉丝点击