P2574 XOR的艺术

· · 题解

XOR的艺术

题目前两个字母吼吼吼

一道简单模板题

思路

与平常的线段树不同的是,这次不是区间加法,区间乘法等基础操作,而是神奇的取反,让我不由自主的想到题目XOR(嘻嘻嘻QAQ) 那我们怎么办呢??只有01哦,不错!!

请看神奇的栗子一枚

区间中取反,我们只需要求的是和,伤害值是1的个数,不就是和嘛!!哈哈哈!!!

看,10101,有3个1,取反过后,01010,就变成2个1啦!!就是5-3=2

在看,00110,有2个1,取反过后,11001,就变成2个1啦!!就是5-2=3

所以呢,区间和,每次在下传懒惰标记的时候呢,就变成区间长度减去自身的值就阔以啦!!!

棒棒哒!!

上代码吧!!!蒟蒻代码,不喜勿喷

至于一些头文件定义什么的省略啦,空间不够,嘻嘻嘻!!!

struct node
{
    int left;//区间左端点
    int right;//右端点
    int w;//初值
    int v;//标记
}tree[Maxn*2];

void Build_Tree(int index,int l,int r)//神奇建树,连函数名都是那么的直接。。。
{
    tree[index].left=l;
    tree[index].right=r;
    if(l==r) {
        tree[index].w=a[l];
        return;
    }
    int mid=(l+r)/2;
    Build_Tree(index*2,l,mid);
    Build_Tree(index*2+1,mid+1,r);
    tree[index].w=tree[index*2].w+tree[index*2+1].w;
}//建树很简单,不说啦!!

void Spread(int index)//下传懒惰标记
{
    if(tree[index].v) {
        tree[index*2].w=tree[index*2].right-tree[index*2].left+1-tree[index*2].w;//如上所说修改
        tree[index*2+1].w=tree[index*2+1].right-tree[index*2+1].left+1-tree[index*2+1].w;
        tree[index*2].v^=1;//标记很简单,就直接取反好啦!!
        tree[index*2+1].v^=1;
        tree[index].v=0;//别忘记清空!!
    }
}

int Query(int index,int l,int r)//自认为好理解的查询。。。
{
    if(tree[index].left>=l&&tree[index].right<=r) return tree[index].w;//如果完全包含,返回区间
    int mid=(tree[index].left+tree[index].right)/2;
    int ans=0;
    Spread(index);//下传标记
    if(l<=mid) ans+=Query(index*2,l,r);//继续向下
    if(r>mid) ans+=Query(index*2+1,l,r);
    return ans;
}

void Change(int index,int l,int r)//修改区间很简单,不说啦!!!
{
    if(tree[index].left>=l&&tree[index].right<=r) {
        tree[index].w=tree[index].right-tree[index].left+1-tree[index].w;
        tree[index].v^=1;
        return;
    }
    int mid=(tree[index].left+tree[index].right)/2;
    Spread(index);
    if(l<=mid) Change(index*2,l,r);
    if(r>mid) Change(index*2+1,l,r);
    tree[index].w=tree[index*2].w+tree[index*2+1].w;
}

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        scanf("%1d",&a[i]);
    Build_Tree(1,1,n);
    for(int i=1; i<=m; i++) {
        cin>>z;
        if(z==0) {
            cin>>x>>y;
            Change(1,x,y);  
        }
        else {
            cin>>x>>y;
            cout<<Query(1,x,y)<<endl;   
        }
    }
    return 0;
}
没啦,蒟蒻望大家多多支持!!!!