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-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
4 4
1 2 4 7
SUM 0 2
XOR 5 0 0
OR 6 0 3
SUM 0 2

Sample Output

7
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.

Source

“高教社杯”第三届福建省大学生程序设计竞赛

 

【题解】:

    这题思路想到 经过多次操作之后的区间应该是一个数字很多相同的区间:

   因为如果相邻两个数经过操作之后变成相同的数了,那么再经过覆盖了该区间的操作时,那么他们的值将同时发生改变,变成另外一个相同的值,这多次操作下去,之后将生更多的相同的数字区间,这里的相同数字就是懒惰标记更新的关键:例如:OR 6 0 3, A=[6 6 6 7];    其中6出现了3次

详见代码:

【code】:

  1 /**
  2 status:Accepted     language:Visual C++
  3 time:1953 ms   memory:47156KB
  4 code length:2686B   author:cj
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <cstring>
  9 #define N 1000010
 10 #define lson p<<1
 11 #define rson p<<1|1
 12 using namespace std;
 13 
 14 struct Nod
 15 {
 16     int l,r;
 17     int num;  //标记区间数字是否相同
 18 }node[N<<2];
 19 
 20 void building(int l,int r,int p)
 21 {
 22     node[p].l = l;
 23     node[p].r = r;
 24     node[p].num = -1;
 25     if(l==r)
 26     {
 27         scanf("%d",&node[p].num);
 28         return;
 29     }
 30     int mid = (l+r)>>1;
 31     building(l,mid,lson);
 32     building(mid+1,r,rson);
 33     if(node[lson].num!=-1&&node[lson].num==node[rson].num)  //向上更新
 34     {
 35         node[p].num = node[lson].num;
 36     }
 37 }
 38 
 39 int opreate(int op,int opn,int num)  //操作函数 op:操作符 opn,num:操作数
 40 {
 41     if(op==1)   return opn&num;
 42     if(op==2)   return opn|num;
 43     if(op==3)   return opn^num;
 44 
 45 }
 46 
 47 void update(int l,int r,int p,int opn,int op)
 48 {
 49     if(node[p].l==l&&node[p].r==r&&node[p].num>=0)  //当找到区间并且区间被相同的数覆盖
 50     {
 51         node[p].num = opreate(op,opn,node[p].num);
 52         return;
 53     }
 54     if(node[p].num>=0) //经过该区间时,向下更新
 55     {
 56         node[lson].num = node[rson].num = node[p].num;
 57         node[p].num = -1;
 58     }
 59     int mid = (node[p].l+node[p].r)>>1;
 60     if(r<=mid)  update(l,r,lson,opn,op);
 61     else if(l>mid)  update(l,r,rson,opn,op);
 62     else
 63     {
 64         update(l,mid,lson,opn,op);
 65         update(mid+1,r,rson,opn,op);
 66     }
 67     if(node[lson].num!=-1&&node[lson].num==node[rson].num)  //向上更新
 68     {
 69         node[p].num = node[lson].num;
 70     }
 71 }
 72 
 73 __int64 query(int l,int r,int p)
 74 {
 75     if(node[p].l==l&&node[p].r==r&&node[p].num>=0)
 76     {
 77         return node[p].num*(node[p].r-node[p].l+1);
 78     }
 79     if(node[p].num>=0)  //经过该区间时,向下更新
 80     {
 81         node[lson].num = node[rson].num = node[p].num;
 82         node[p].num = -1;
 83     }
 84     int mid = (node[p].l+node[p].r)>>1;
 85     if(r<=mid)  return query(l,r,lson);
 86     else if(l>mid)  return query(l,r,rson);
 87     else return query(l,mid,lson)+query(mid+1,r,rson);
 88     if(node[lson].num!=-1&&node[lson].num==node[rson].num)  //向上更新
 89     {
 90         node[p].num = node[lson].num;
 91     }
 92 }
 93 
 94 int main()
 95 {
 96     int t;
 97     scanf("%d",&t);
 98     while(t--)
 99     {
100        int n,m;
101        scanf("%d%d",&n,&m);
102        char op[5];
103        building(1,n,1);
104        while(m--)
105        {
106             scanf("%s",op);
107             int opn,a,b;
108             if(op[0]=='S')
109             {
110                 scanf("%d%d",&a,&b);
111                 printf("%I64d\n",query(a+1,b+1,1));
112             }
113             else
114             {
115                 scanf("%d%d%d",&opn,&a,&b);
116                 if(op[0]=='A')  update(a+1,b+1,1,opn,1);
117                 else if(op[0]=='O')  update(a+1,b+1,1,opn,2);
118                 else if(op[0]=='X')  update(a+1,b+1,1,opn,3);
119             }
120        }
121     }
122     return 0;
123 }

 

posted @ 2013-08-05 21:57  crazy_apple  阅读(862)  评论(0编辑  收藏  举报