zoukankan      html  css  js  c++  java
  • Coderforces 242E XOR on Segment

    题意:给定一个序列,要求完成俩个操作

    1)查询区间[l,r] 的和

    2)区间更新, 区间每一个数都异或一个数x

    对每一个查询输出结果

    分析:对区间更新和查询这种操作,比较明显的就想到了线段树。区间查询比较简单,关键是区间更新该如何解决。

    我们为线段数的每一个节点开一个cnt[20] 的数组,保存该区间内每一个数二进制位上1的个数,cnt[0] 表示对应区间内所有数第一个二进制数上1的个数和,这样,针对每一个异或操作,我们可以这样解决:

    		for(int i = 0; i < L; ++i)
    		{
    			if(!(v & ( 1 << i) )) continue;//针对异或操作的性质,如果v的第i位为0,则这个区间内,第i位上的1的个数不变;
                                    //若第i位为1,则第i为上1 的个数和0 的个数互换 p[k].cnt[i] = p[k].r-p[k].l + 1 - p[k].cnt[i]; }

    这样,在计算区间和时

    		for(int i = 0; i < L; ++i)
    			ans += ((p[k].cnt[i] * 1ll) << i);
    

    当然,要加速对区间更新的操作,肯定要运用lazy的思想

    完整代码
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    const int N = 100000 + 10;
    const int L = 20; 
    
    struct Node
    {
        int l,r;
        int c,cnt[L];//cnt[i] 表示区间[l,r]内二进制第i位上1的个数
    }p[3*N];
    int que[N];
     
    void build(int k,int s,int t)
    {
        int kl, kr, mid;
        p[k].l = s; p[k].r = t;p[k].c = 0;
        if(s == t) {
            for(int i = 0; i < L; ++i)
            {
                if(que[s] & ( 1 << i ))  
                    p[k].cnt[i] = 1;
            }
            return ;
        }
        mid=(s + t) >> 1; kl = k << 1; kr = kl + 1;
        build(kl, s, mid);
        build(kr, mid+1, t);
        for(int i = 0; i < L; ++i)
            p[k].cnt[i] = p[kl].cnt[i] + p[kr].cnt[i];
    }
    
    void Push_Down(int k, int v)
    {
            p[k].c ^= v;
            for(int i = 0; i < L; ++i)
            {
                if(!(v & ( 1 << i) )) continue;
                p[k].cnt[i] = p[k].r-p[k].l + 1 - p[k].cnt[i];
            }
    }
     
    void insert(int k,int s,int t,int v)
    {
        if(s <= p[k].l&& t >= p[k].r)
        {
            Push_Down(k, v);
            return ;
        }
        else {
    
            int mid=(p[k].r + p[k].l) >> 1, kl = k << 1, kr = kl + 1;
            if(p[k].c != 0)
            {
                Push_Down(kl, p[k].c);
                Push_Down(kr, p[k].c);
                p[k].c = 0;
            }
            if(s <= mid) insert(kl, s, t, v);
            if(t > mid) insert(kr, s, t, v);
            for(int i = 0; i < L; ++i)
                p[k].cnt[i] = p[kr].cnt[i] + p[kl].cnt[i];
        }
    }
     
    __int64 query(int k,int s,int t)
    {
        if(s <= p[k].l && t >= p[k].r)
        {
            __int64 ans = 0;
            for(int i = 0; i < L; ++i)
                ans += ((p[k].cnt[i] * 1ll) << i);
            return ans;
        }
    
        int mid=(p[k].r + p[k].l) >> 1,kl = k << 1,kr = kl + 1;
    
        if(p[k].c)
        {
            Push_Down(kl, p[k].c);
            Push_Down(kr, p[k].c);
            p[k].c = 0;
        }
        __int64 a = 0,b = 0;
        if(s <= mid) a = query(kl,s,t);
        if(t > mid) b = query(kr,s,t);
        for(int i = 0; i < L; ++i)
            p[k].cnt[i] = p[kl].cnt[i] + p[kr].cnt[i];
        return a + b;
    }
     
    int main()
    {
        int i,n,m,a,b,t,k;
        scanf("%d",&n);
            for(i = 1; i <= n; ++i) scanf("%d",que + i);
            build(1,1,n);
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d",&k);
                if(k == 1)
                {
                   scanf("%d %d",&a,&b);
                   printf("%I64d\n",query(1,a,b));
                }
                else
                {
                   scanf("%d %d %d",&a,&b,&t);
                   if(t != 0)
                       insert(1,a,b,t);
                }
            }
        return 0;
    }
  • 相关阅读:
    io学习
    asp.net文件上传进度条研究
    asp.net页面中的Console.WriteLine结果如何查看
    谨慎跟随初始目的不被关联问题带偏
    android 按钮特效 波纹 Android button effects ripple
    安卓工作室 日志设置
    安卓工作室 文件浏览器 android studio File browser
    一个新的Android Studio 2.3.3可以在稳定的频道中使用。A new Android Studio 2.3.3 is available in the stable channel.
    新巴巴运动网上商城 项目 快速搭建 教程 The new babar sports online mall project quickly builds a tutorial
    码云,git使用 教程-便签
  • 原文地址:https://www.cnblogs.com/nanke/p/2952610.html
Copyright © 2011-2022 走看看