Accept: 11 Submit: 64
Time Limit: 10000 mSec Memory Limit : 262144 KB
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
Sample Input
Sample Output
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.
Cached at 2012-12-03 14:54:45.
解题思路:数最大为15于是可以统计2进制的个数。线段树主要是Down的时候要考虑,对于每个二进制位我考虑4种操作:&0 -> 0, |1 -> R-L+1, ^1 -> R-L+1-cnt, 其他为不变。
则代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstring>
using namespace std;
const int ROOT = 1;
const int MAXN = 1000010;
struct Node
{
int L, R;
int cnt[4], op[4];
Node(int L =0, int R =0): L(L), R(R) { memset(op, -1, sizeof(op)); }
};
Node node[4*MAXN];
int num[MAXN];
inline int pL(int x) { return x<<1; }
inline int pR(int x) { return (x<<1)|1; }
void BuildTree(int L, int R, int root)
{
node[root] = Node(L, R);
if (L == R)
{
for ( int i =0; i < 4; ++i) node[root].cnt[i] = num[L]&(1<<i) ? 1 : 0;
return;
}
int M = (L+R)>>1;
BuildTree(L, M, pL(root));
BuildTree(M+1, R, pR(root));
for ( int i =0; i < 4; i++)
node[root].cnt[i] = node[pL(root)].cnt[i] + node[pR(root)].cnt[i];
}
inline int Cnt(Node &n, int i) { return n.op[i]==0 ? 0 : n.op[i]==1 ? n.R-n.L+1 : n.op[i]==2 ? n.R-n.L+1-n.cnt[i] : n.cnt[i]; }
void Update(int root)
{
Node &n = node[root];
if (n.L == n.R)
for ( int i =0; i < 4; n.op[i++] = -1) n.cnt[i] = Cnt(n, i);
else
for ( int i =0; i < 4; n.op[i++] = -1) n.cnt[i] = Cnt(node[pL(root)], i) + Cnt(node[pR(root)], i);
}
void Down(int root)
{
Node &n = node[root];
if (n.L != n.R)
{
Node &lc = node[pL(root)], &rc = node[pR(root)];
for ( int i =0; i < 4; ++i)
if (n.op[i] == 0 || n.op[i] == 1) lc.op[i] = rc.op[i] = n.op[i];
else if (n.op[i] == 2)
lc.op[i] = lc.op[i]==-1 ? 2 : 2-lc.op[i]-1,
rc.op[i] = rc.op[i]==-1 ? 2 : 2-rc.op[i]-1;
}
}
void Sunshine(int L, int R, int p, int m, int root)
{
Node &n = node[root];
Down(root);
if (L==n.L && R==n.R)
{
Update(root);
if (p == 0) for ( int i =0; i < 4; ++i) n.op[i] = (m & (1<<i))==0 ? 0 : -1;
else if (p == 1) for ( int i =0; i < 4; ++i) n.op[i] = (m & (1<<i)) ? 1 : -1;
else if (p == 2) for ( int i =0; i < 4; ++i) n.op[i] = (m & (1<<i)) ? 2 : -1;
return;
}
Node &lc = node[pL(root)], &rc = node[pR(root)];
if (R <= lc.R) Sunshine(L, R, p, m, pL(root));
else if (L >= rc.L) Sunshine(L, R, p, m, pR(root));
else {
Sunshine(L, lc.R, p, m, pL(root));
Sunshine(rc.L, R, p, m, pR(root));
}
Update(root);
}
int Sum(Node &n)
{
int res = 0; for ( int i =0; i < 4; ++i) res += Cnt(n, i) << i;
return res;
}
int Query(int L, int R, int root)
{
Node &n = node[root];
Down(root); Update(root);
if (n.L==L && n.R==R) return Sum(n);
Node &lc = node[pL(root)], &rc = node[pR(root)];
if (R <= lc.R) return Query(L, R, pL(root));
if (L >= rc.L) return Query(L, R, pR(root));
return Query(L, lc.R, pL(root)) + Query(rc.L, R, pR(root));
}
void Print(int root)
{
Node &n = node[root];
printf("L: %d, R: %d, %d, %d, %d, %d..\n", n.L, n.R, n.cnt[0], n.cnt[1], n.cnt[2], n.cnt[3]);
for ( int i =0; i < 4; i++) cout << n.op[i] << " "; cout << endl;
if (n.L == n.R) return;
Print(pL(root));
Print(pR(root));
}
int main()
{
freopen("h:\\data.in", "r", stdin);
freopen("h:\\data.out", "w", stdout);
int T, n, m, a, b, c, op;
for ( scanf("%d", &T); T--; )
{
scanf("%d%d", &n, &m);
for ( int i =0; i < n; ++i) scanf("%d", num+i);
BuildTree(0, n-1, ROOT);
for ( char s[20]; m--; )
{
scanf("%s%d%d", s, &a, &b);
if (strcmp(s, "SUM") == 0)
{
printf("%d\n", Query(a, b, ROOT));
continue;
}
scanf("%d", &c);
op = strcmp(s, "AND")==0 ? 0 : strcmp(s, "OR")==0 ? 1 : 2;
Sunshine(b, c, op, a, ROOT);
}
}
return 0;
}