【题目链接】 http://acm.fzu.edu.cn/problem.php?pid=2105

【题目大意】

  给出一个序列,数字均小于16,为正数,每次区间操作可以使得
    1. [l,r]区间and一个数
    2. [l,r]区间or一个数
    3. [l,r]区间xor一个数
    4. [l,r]区间查询和
  操作数均为小于16的非负整数

【题解】

  由于操作数很小,因此我们可以按位维护四棵线段树,表示二进制中的第i位,
  对于and操作,只有当and的当前位为0时才对区间有影响,效果是将区间全部变为0,
  对于or和xor操作,当前位为1的时候才对区间有影响,
  因为and和or是全区间变化为同一个值,因此区间和会变为全区间或者0,
  那么and和or的变化只需要看父区间的值来决定子区间的变化而不需要标记传递
  对于xor操作,相当于区间01翻转,用一个标记记录翻转次数即可,

【代码】

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int N=1000010;
  5. int T[4][N<<2],tag[4][N<<2],a[N];
  6. void up(int k,int x){T[k][x]=T[k][x<<1]+T[k][x<<1|1];}
  7. void pb(int k,int x,int l,int r){
  8. int mid=(l+r)>>1;
  9. if(T[k][x]==r-l+1){T[k][x<<1]=mid-l+1;T[k][x<<1|1]=r-mid;}
  10. if(!T[k][x]){T[k][x<<1]=T[k][x<<1|1]=0;}
  11. if(tag[k][x]){
  12. tag[k][x]^=1;
  13. if(T[k][x]!=r-l+1&&T[k][x]){
  14. T[k][x<<1]=mid-l+1-T[k][x<<1];
  15. T[k][x<<1|1]=r-mid-T[k][x<<1|1];
  16. }tag[k][x<<1]^=1;tag[k][x<<1|1]^=1;
  17. }
  18. }
  19. void build(int k,int x,int l,int r){
  20. int mid=(l+r)>>1;
  21. tag[k][x]=0;
  22. if(l==r){T[k][x]=(a[l]>>k)&1;return;}
  23. build(k,x<<1,l,mid);build(k,x<<1|1,mid+1,r);
  24. up(k,x);
  25. }
  26. void update(int k,int x,int l,int r,int L,int R,char op){
  27. int mid=(l+r)>>1;
  28. if(L<=l&&r<=R){
  29. if(op=='A')T[k][x]=0;
  30. if(op=='O')T[k][x]=r-l+1;
  31. if(op=='X')T[k][x]=(r-l+1)-T[k][x],tag[k][x]^=1;
  32. return;
  33. }pb(k,x,l,r);
  34. if(L<=mid)update(k,x<<1,l,mid,L,R,op);
  35. if(mid+1<=R)update(k,x<<1|1,mid+1,r,L,R,op);
  36. up(k,x);
  37. }
  38. int query(int k,int x,int l,int r,int L,int R){
  39. int mid=(l+r)>>1;
  40. if(L<=l&&r<=R)return T[k][x]; pb(k,x,l,r);
  41. int res=0;
  42. if(L<=mid)res+=query(k,x<<1,l,mid,L,R);
  43. if(mid+1<=R)res+=query(k,x<<1|1,mid+1,r,L,R);
  44. return res;
  45. }
  46. int Cas,n,m;
  47. char op[10];
  48. int main(){
  49. scanf("%d",&Cas);
  50. while(Cas--){
  51. scanf("%d%d",&n,&m);
  52. for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  53. for(int i=0;i<4;i++)build(i,1,1,n);
  54. while(m--){
  55. scanf("%s",op);
  56. if(op[0]=='S'){
  57. int l,r,ans=0;
  58. scanf("%d%d",&l,&r);
  59. l++;r++;
  60. for(int i=0;i<4;i++)ans+=query(i,1,1,n,l,r)*(1<<i);
  61. printf("%d\n",ans);
  62. }else{
  63. int l,r,x;
  64. scanf("%d%d%d",&x,&l,&r); l++,r++;
  65. for(int i=0;i<4;i++)if((op[0]=='A')^((x>>i)&1))update(i,1,1,n,l,r,op[0]);
  66. }
  67. }
  68. }return 0;
  69. }

FZU 2105 Digits Count(按位维护线段树)的更多相关文章

  1. ACM: FZU 2105 Digits Count - 位运算的线段树【黑科技福利】

     FZU 2105  Digits Count Time Limit:10000MS     Memory Limit:262144KB     64bit IO Format:%I64d & ...

  2. FZU 2105 Digits Count(线段树)

    Problem 2105 Digits Count Accept: 302 Submit: 1477 Time Limit: 10000 mSec Memory Limit : 262144 KB P ...

  3. FZU 2105 Digits Count

     Problem 2105 Digits Count Accept: 444    Submit: 2139 Time Limit: 10000 mSec    Memory Limit : 2621 ...

  4. FZU 2105 Digits Count(位数计算)

    Description 题目描述 Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operation ...

  5. fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛

    http://acm.fzu.edu.cn/problem.php?pid=2105 Problem Description Given N integers A={A[0],A[1],...,A[N ...

  6. FZU2105 Digits Count(按位建线段树)题解

    题意: 给出区间与.或.异或\(x\)操作,还有询问区间和. 思路: 因为数比较小,我们给每一位建线段树,这样每次只要更新对应位的答案. 与\(0\)和或\(1\)相当于重置区间,异或\(1\)相当于 ...

  7. 【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和

    题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是 ...

  8. FOJ 2105 Digits Count

    题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作. 思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制. and 如果该为是1  直接无视,是0则成段赋值为0: or  如 ...

  9. HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)

    题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...

随机推荐

  1. Sketch VS Photoshop

    参考:http://mp.weixin.qq.com/s?__biz=MjM5NTQ5MjIyMA==&mid=217309554&idx=4&sn=4d6a5239ca813 ...

  2. sublime在搜索的时候排除js文件

    代码审计的时候sublime是一个神器.所以.... Ctrl + Shift + F /home/i3ekr/Desktop/coding/phpcms,*.php 这样就可以直接搜索所有的php文 ...

  3. js/jq 键盘上下左右回车按键

    js判断上下左右回车按键: document.onkeydown=function(e){ e=window.event||e; switch(e.keyCode){ case 37: //左键 co ...

  4. KVM初始化过程

    转载:http://blog.csdn.net/dashulu/article/details/17074675 之前打算整理一下在Guest VM, KVM, QEMU中IO处理的整个流程,通过查阅 ...

  5. java数组面试题

    一维数组可以写成:int[ ]x 或者int x[ ]: 二维数组可以写成:int[ ] y [ ] 或者int y[ ][ ] 或者int [ ][ ]y 面试题如下:       声明数组int[ ...

  6. 在ubuntu上配置LAMP架构

    1. 安装MySQL /* ubuntu默认进入系统是普通用户 所以在真实工作中,我们会得到root的授权. 所以我们需要用sudo做一切只有root才能完成的操作. */ [root@LAMP ~] ...

  7. .NET直接编译成本地代码:.NET Native架构简介

    原文地址:http://blog.csdn.net/atfield/article/details/23449089

  8. CSS3新属性解释及用法

    一. transition(a标签hover渐隐效果) a:hover{transition: color 0.15s linear 0s, background-color 0.3s linear ...

  9. jdbc连接远程数据库进行操作

    链接远程数据库的时候,要把获得链接的url进行修改 1 package com.test; import java.sql.Connection; import java.sql.DriverMana ...

  10. Python+Selenium 自动化实现实例-Link 捕捉元素的几种方法

    from selenium import webdriver driver = webdriver.Chrome() driver.get("http://www.baidu.com&quo ...