FZU 2105  Digits Count

Time Limit:10000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u

Description

Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations:

Operation 1: AND opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] AND opn (here "AND" is bitwise operation).

Operation 2: OR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] OR opn (here "OR" is bitwise operation).

Operation 3: XOR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] XOR opn (here "XOR" is bitwise operation).

Operation 4: SUM L R

We want to know the result of A[L]+A[L+1]+...+A[R].

Now can you solve this easy problem?

Input

The first line of the input contains an integer T, indicating the number of test cases. (T≤100)

Then T cases, for any case, the first line has two integers n and m (1≤n≤1,000,000, 1≤m≤100,000), indicating the number of elements in A and the number of operations.

Then one line follows n integers A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n).

Then m lines, each line must be one of the 4 operations above. (0≤opn≤15)

Output

For each test case and for each "SUM" operation, please output the result with a single line.

Sample Input

  1. 1
  2. 4 4
  3. 1 2 4 7
  4. SUM 0 2
  5. XOR 5 0 0
  6. OR 6 0 3
  7. SUM 0 2

Sample Output

  1. 7
  2. 18

Hint

A = [1 2 4 7]

SUM 0 2, result=1+2+4=7;

XOR 5 0 0, A=[4 2 4 7];

OR 6 0 3, A=[6 6 6 7];

SUM 0 2, result=6+6+6=18.

  1. /*/
  2. 题意:
  3. 给出一组数,然后有4种操作。
  4.  
  5. AND opn l r 对 l~r 段的数与 opn 进行&运算;
  6.  
  7. OR opn l r 对 l~r 段的数与 opn 进行|运算;
  8.  
  9. XOR opn l r 对 l~r 段的数与 opn 进行^运算;
  10.  
  11. SUMl r 对 l~r 段的数求和,并输出。
  12.  
  13. 很明显的线段树,可是我还是太年轻。一开始以为只是一棵裸树,结果写到一半,发现不能对求和的数再进行与或非的运算,也不知道我哪里来的勇气,想到,既然不能对和去运算,不如把lazy全压下去。。。MDZZ。。。
  14.  
  15. 后来,队友提示我可以用二进制来存数,然后与或非的情况也就变得特别简单了。
  16.  
  17. 然后就用关于二进制的线段树来写了这个,思路一开始是很混乱的,不过写到后面还是被 >> 和 << 坑了好久,还是修行不精啊。。。
  18.  
  19. A了但是运行时间还是比较久。
  20.  
  21. 最后集训队队长发了个福利,读入优化,速度爆炸了,又是我的代码运行速度第一(233333)。
  22.  
  23. AC代码:
  24. /*/
  1. #include"algorithm"
  2. #include"iostream"
  3. #include"cstring"
  4. #include"cstdlib"
  5. #include"cstdio"
  6. #include"string"
  7. #include"vector"
  8. #include"stack"
  9. #include"queue"
  10. #include"cmath"
  11. #include"map"
  12. using namespace std;
  13. typedef long long LL ;
  14. #define lson l,m,rt<<1
  15. #define rson m+1,r,rt<<1|1
  16. #define FK(x) cout<<"["<<x<<"]\n"
  17. #define memset(x,y) memset(x,y,sizeof(x))
  18. #define memcpy(x,y) memcpy(x,y,sizeof(x))
  19. #define smallfor(T) for(int i=0 ;i<T ;i++)
  20. #define bigfor(T) for(int qq=1;qq<= T ;qq++)
  21.  
  22. const int MX =1111111;
  23. const int INF=0x3f3f3f3f;
  24. int sum[MX<<2][4],lazy[MX<<2][4];
  25. void PushUp(int rt,int i) {
  26. sum[rt][i]=sum[rt<<1][i]+sum[rt<<1|1][i];
  27. }
  28.  
  29. void PushDown(int rt,int m,int i) {
  30. if(lazy[rt][i]==0) { //如果进行了AND操作,并且该位为0 清空下面子树。
  31. lazy[rt<<1][i]=0;
  32. lazy[rt<<1|1][i]=0;
  33. sum[rt<<1][i]=sum[rt<<1|1][i]=0;
  34. }
  35. if(lazy[rt][i]==1) { //如果进行了OR 操作,并且该位为1 填满下面子树。
  36. lazy[rt<<1][i]=1;
  37. lazy[rt<<1|1][i]=1;
  38. sum[rt<<1][i]=m-(m>>1);
  39. sum[rt<<1|1][i]=m>>1;
  40. }
  41. if(lazy[rt][i]==2) { //如果进行了XOR操作
  42. if(lazy[rt<<1][i]==INF) { //如果没有进行过任何操作,标记为XOR操作
  43. lazy[rt<<1][i]=2;
  44. sum[rt<<1][i]=m-(m>>1)-sum[rt<<1][i];
  45. } else if(lazy[rt<<1][i]==2) { //如果进行过XOR操作,a^b^b==a 恢复操作内容。
  46. lazy[rt<<1][i]=INF;
  47. sum[rt<<1][i]=m-(m>>1)-sum[rt<<1][i];
  48. } else { //如果进行了操作并且不是XOR操作 将该操作再取XOR操作
  49. lazy[rt<<1][i]^=1;
  50. if(lazy[rt<<1][i]==0) sum[rt<<1][i]=0;
  51. else sum[rt<<1][i]=m-(m>>1);
  52. }
  53. // 另一棵子树用同样的方法处理
  54.  
  55. if(lazy[rt<<1|1][i]==INF) {
  56. lazy[rt<<1|1][i]=2;
  57. sum[rt<<1|1][i]=(m>>1)-sum[rt<<1|1][i];
  58. } else if(lazy[rt<<1|1][i]==2) {
  59. lazy[rt<<1|1][i]=INF;
  60. sum[rt<<1|1][i]=(m>>1)-sum[rt<<1|1][i];
  61. } else {
  62. lazy[rt<<1|1][i]^=1;
  63. if(lazy[rt<<1|1][i]==0) sum[rt<<1|1][i]=0;
  64. else sum[rt<<1|1][i]=(m>>1);
  65. }
  66. }
  67. lazy[rt][i]=INF; //标记lazy为空
  68. }
  69.  
  70. void Build(int l,int r,int rt) {
  71. for(int i=0; i<4; i++) lazy[rt][i]=INF; //清空懒惰标记
  72. if(r==l) {
  73. int temp;
  74. scanf("%d",&temp);
  75. // FK("temp=="<<temp);
  76. for(int i=0; i<4; i++) {
  77. sum[rt][i]=(bool)(temp&(1<<i));//【这里一定要取(bool)否则得到的值不会是1,而是比 1大的数】
  78. // 该题目的方法是用sum保存每个位上值的总数,再改变为10进制,求和。
  79. // 把数按照二进制保存在4个位上面
  80. // FK(sum[rt][i]);
  81. }
  82. return;
  83. }
  84. int m=(r+l)>>1;
  85. Build(lson);
  86. Build(rson);
  87. for(int i=0; i<4; i++) PushUp(rt,i);
  88. }
  89.  
  90. void UpData(int L,int R,int v,int i,int l,int r,int rt) {
  91. if(r<=R&&L<=l) {
  92. switch(v) {
  93. case 0:
  94. sum[rt][i]=0,lazy[rt][i]=v;
  95. //如果是进行AND操作,并且是0,清空和。
  96. break;
  97. case 1:
  98. sum[rt][i]=r-l+1,lazy[rt][i]=v;
  99. //如果是进行OR 操作,并且是1,填满和。
  100. break;
  101. case 2:
  102. sum[rt][i]=r-l+1-sum[rt][i];
  103. if(lazy[rt][i]==2) lazy[rt][i]=INF;
  104. else if(lazy[rt][i]==INF) lazy[rt][i]=2;
  105. else lazy[rt][i]^=1;
  106. break;
  107. default:
  108. break;
  109. }
  110. return ;
  111. }
  112. PushDown(rt,r-l+1,i);
  113. int m=(r+l)>>1;
  114. if(L<=m)UpData(L,R,v,i,lson);
  115. if(R>m) UpData(L,R,v,i,rson);
  116. PushUp(rt,i);
  117. }
  118.  
  119. int Query(int L,int R,int i,int l,int r,int rt) {
  120. if(L<=l&&r<=R) {
  121. return sum[rt][i];
  122. // 返回这个数该位的和。
  123. }
  124. int m=(r+l)>>1;
  125. int sum=0;
  126. PushDown(rt,r-l+1,i);
  127. if(L<=m)sum+=Query(L,R,i,lson);
  128. if(R>m) sum+=Query(L,R,i,rson);
  129. return sum;
  130. }
  131.  
  132. int main() {
  133. int T;
  134. scanf("%d",&T);
  135. bigfor(T) {
  136. int n,m;
  137. scanf("%d%d",&n,&m);
  138. char op[5];
  139. Build(0,n-1,1);
  140. // FK("Build Success!");
  141. for(int i=0; i<m; i++) {
  142. scanf("%s",op);
  143. if(op[0]=='S') {
  144. int l,r;
  145. int ans=0;
  146. scanf("%d%d",&l,&r);
  147. for(int j=0; j<4; j++) ans+=Query(l,r,j,0,n-1,1)<<j;
  148. // 将每一位的数字和用10进制进位后相加。
  149. printf("%d\n",ans);
  150. } else {
  151. int opn,l,r;
  152. char v;
  153. scanf("%d%d%d",&opn,&l,&r);
  154. if(op[0]=='A') { //AND为&如果某位上为 1 那么值不变 否则全变为0;【区间覆盖】
  155. for(int j=0; j<4; j++) {
  156. int x=opn&(1<<j);
  157. // FK("j=="<<j<<" x=="<<x);
  158. if(!x)UpData(l,r,0,j,0,n-1,1);
  159. }
  160. }
  161. if(op[0]=='O') { //OR 为|如果某位上为 0 那么值不变 否则全变为1;【区间覆盖】
  162. for(int j=0; j<4; j++) {
  163. int x=opn&(1<<j);
  164. // FK("j=="<<j<<" x=="<<x);
  165. if(x)UpData(l,r,1,j,0,n-1,1);
  166. }
  167. }
  168. if(op[0]=='X') { //XOR为^如果某位上为 0 那么值不变 否则0->1,1->0【区间更新】
  169. for(int j=0; j<4; j++) {
  170. int x=opn&(1<<j);
  171. // FK("j=="<<j<<" x=="<<x);
  172. if(x)UpData(l,r,2,j,0,n-1,1);
  173. }
  174. }
  175. }
  176. }
  177. }
  178. return 0;
  179. }
  1.  

    

  1. //下面是快速读入的福利【只适用于读入比较多的题目,适用于题目原本复杂度为O(n),但是自己的代码估计会是O(nlog(n)),这个优化的作用就会比较明显。】
  2.  
  3. //下面就是黑科技:
  1. namespace IO {
  2. const int MT = 5e7; //1e711000kb
  3. char buf[MT];
  4. int c, sz;
  5. void begin() {
  6. c = 0;
  7. sz = fread(buf, 1, MT, stdin);
  8. }
  9. inline bool read(int &t) {
  10. while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
  11. if(c >= sz) return false;
  12. bool flag = 0;
  13. if( buf[c] == '-')flag = 1, c++;
  14. for(t = 0; c < sz && '0' <= buf[c] && buf[c] <='9'; c++) t = t * 10 + buf[c] - '0';
  15. if(flag) t = -t;
  16. return true;
  17. } inline bool read(char s[]) {
  18. while(c < sz && (buf[c] == ' ' || buf[c] == '\n')) c++;
  19. if(c >= sz) return false;
  20. int len = 0;
  21. while(c < sz && buf[c] != ' ' && buf[c] != '\n') s[len++] = buf[c] , c++;
  22. s[len]=0;
  23. return true;
  24. }
  25. }
  26. using namespace IO;
  27.  
  28. //打开方式:
  29.  
  30. int x;
  31. read(x);
  1.  

  

  1.  
  1.  

  

  1.  

ACM: FZU 2105 Digits Count - 位运算的线段树【黑科技福利】的更多相关文章

  1. FZU 2105 Digits Count(线段树)

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

  2. FZU 2105 Digits Count

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

  3. FZU 2105 Digits Count(按位维护线段树)

    [题目链接] http://acm.fzu.edu.cn/problem.php?pid=2105 [题目大意] 给出一个序列,数字均小于16,为正数,每次区间操作可以使得 1. [l,r]区间and ...

  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. HDU 6186 CS Course【前后缀位运算枚举/线段树】

    [前后缀枚举] #include<cstdio> #include<string> #include<cstdlib> #include<cmath> ...

  7. FOJ 2105 Digits Count

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

  8. HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...

  9. Count the Colors(线段树染色)

    Count the Colors Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu Submit ...

随机推荐

  1. 搭建consul 集群

    1.   准备工作 a)      启动三台虚拟机 s1:10.1.7.141 s2:10.1.7.139 s3:10.1.7.138 b)      每台机器上在 /home新建文件夹 mkdir ...

  2. Eclipse使用Maven tomcat:run命令启动web项目时修改默认端口

  3. [CodeWars][JS]实现大整数加法

    问题描述 实现‘字符串加法’,即将两个以字符串形式表示的数字相加,得到结果然后返回一个新的字符串. 例如:输入‘123’,‘321’,返回‘444’. 这样在进行两个任意大的整数相加的时候,既不会溢出 ...

  4. ping 或者ssh 发生connect: No buffer space available 错误

    如果遇到这种情况,一般说明你的本地服务器的arp表缓存太大,而服务器内核设定的回收条数太小,一直被回收造成的. 可以用一下命令扩大arp表可以缓存的记录条数: echo 512 > /proc/ ...

  5. shell语法

    基本语法列表 #linux组成:内核+工具 #linux启动: . getty:提示登录名和密码,输入之后调用login . login:login验证用户名和密码,然后调用shell . shell ...

  6. CSS3实现鼠标移动到图片上图片变大

    CSS3实现鼠标移动到图片上图片变大(缓慢变大,有过渡效果,放大的过程是有动画过渡的,这个过渡的时间可以自定义 <!DOCTYPE html><html> <head&g ...

  7. il c井

    base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 将resource 替换成 fileComplier 生成的 resx(可以 ...

  8. connect-flash 中间件

    http://blog.csdn.net/liangklfang/article/details/51086607

  9. DevExpress GridControl 选择整行被选单元格不变色的设置

    设置GridControl 里面的 gridview 属性, 找到OptionSelection 将EnableAppearanceFocusedCell 属性设置False 就可以了 此方式同样适用 ...

  10. IDEA tomcat乱码

    在运行/调试 配置对话框的Startup/Connection面板中, 勾选Pass environment variables. 并添加一个environment variable, Name填 J ...