Accept: 150 Submit: 880
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.
因为数值得范围<16,所以我们可以对每一个二进制位建一棵线段树,一共四棵,然后再进行位运算。
AND:a&1=a,a&0=0,所以只需要考虑操作的数的此位为0的时候,区间变成0
OR:a|1=1,a|0=a,所以只需要考虑操作的数的此位为1的时候,区间变成1
XOR: 1^0=1,0^0=0,1^1=0,0^1=1,所以只需要所以只需要考虑操作的数的此位为1的时候,区间0变1,1变0.
所以开了俩个标记,一个标记前面俩种,一个标记第三种。注意每时每刻,俩标记不能共存。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
typedef long long ll;
#define rep(i,s,t) for(int i=s;i<t;i++)
#define red(i,s,t) for(int i=s-1;i>=t;i--)
#define ree(i,now) for(int i=head[now];i!=-1;i=edge[i].next)
#define clr(a,v) memset(a,v,sizeof a)
#define L t<<1
#define R t<<1|1
#define MID int mid=(l+r)>>1
//#define max(a,b) (a<b?b:a)
//#define min(a,b) (a<b?a:b)
#define lowbit(x) (x&(-x))
#define SQR(a) ((a)*(a))
inline int input(){
int ret=0;bool isN=0;char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') isN=1;
c=getchar();
}
while(c>='0' && c<='9'){
ret=ret*10+c-'0';
c=getchar();
}
return isN?-ret:ret;
}
inline void output(int x){
if(x<0){
putchar('-');x=-x;
}
int len=0,data[11];
while(x){
data[len++]=x%10;x/=10;
}
if(!len) data[len++]=0;
while(len--)
putchar(data[len]+48);
putchar('\n');
}
const int MAXN=1000005;
int lazy[4][MAXN<<2],lazy_xor[4][MAXN<<2];
int len[4][MAXN<<2];
int sum[4][MAXN<<2];
int t,n,m;
int a[MAXN],x,y,z;
char op[5];
inline void pushup(int t,int i){
sum[i][t]=sum[i][L]+sum[i][R];
}
inline void pushdown_or_and(int t,int i){
if(lazy[i][t]!=-1){
lazy_xor[i][L]=lazy_xor[i][R]=0;
lazy[i][L]=lazy[i][R]=lazy[i][t];
sum[i][L]=len[i][L]*lazy[i][L];
sum[i][R]=len[i][R]*lazy[i][R];
lazy[i][t]=-1;
}
}
inline void pushdown_xor(int t,int i){
if(lazy_xor[i][t]){
lazy_xor[i][L]^=1,lazy_xor[i][R]^=1;
sum[i][L]=(len[i][L]-sum[i][L]);
sum[i][R]=(len[i][R]-sum[i][R]);
lazy_xor[i][t]=0;
}
}
inline void build(int t,int l,int r,int i){
len[i][t]=(r-l+1);
lazy[i][t]=-1;
lazy_xor[i][t]=0;
if(l==r){
sum[i][t]=((a[l]&(1<<i))?1:0);
}
else{
MID;
build(L,l,mid,i);
build(R,mid+1,r,i);
pushup(t,i);
}
}
inline void modefiy_or_and(int t,int l,int r,int x,int y,int v,int i){
if(l>=x && r<=y){
lazy_xor[i][t]=0;
lazy[i][t]=v;
sum[i][t]=v*len[i][t];
}
else{
pushdown_or_and(t,i);
pushdown_xor(t,i);
MID;
if(y<=mid) modefiy_or_and(L,l,mid,x,y,v,i);
else if(x>mid) modefiy_or_and(R,mid+1,r,x,y,v,i);
else{
modefiy_or_and(L,l,mid,x,mid,v,i);
modefiy_or_and(R,mid+1,r,mid+1,y,v,i);
}
pushup(t,i);
}
}
inline void modefiy_xor(int t,int l,int r,int x,int y,int i){
if(l>=x && r<=y){
if(lazy[i][t]!=-1){
lazy[i][t]^=1;
sum[i][t]=len[i][t]-sum[i][t];
}
else{
lazy_xor[i][t]^=1;
sum[i][t]=len[i][t]-sum[i][t];
}
}
else{
pushdown_or_and(t,i);
pushdown_xor(t,i);
MID;
if(y<=mid) modefiy_xor(L,l,mid,x,y,i);
else if(x>mid) modefiy_xor(R,mid+1,r,x,y,i);
else{
modefiy_xor(L,l,mid,x,mid,i);
modefiy_xor(R,mid+1,r,mid+1,y,i);
}
pushup(t,i);
}
}
inline int query(int t,int l,int r,int x,int y,int i){
if(l>=x && r<=y) return sum[i][t];
pushdown_or_and(t,i);
pushdown_xor(t,i);
MID;
if(y<=mid) return query(L,l,mid,x,y,i);
else if(x>mid) return query(R,mid+1,r,x,y,i);
else return query(L,l,mid,x,mid,i)+query(R,mid+1,r,mid+1,y,i);
}
int main(){
t=input();
while(t--){
n=input(),m=input();
rep(i,1,n+1) a[i]=input();
rep(i,0,4) build(1,1,n,i);
while(m--){
scanf("%s",op);
if(op[0]=='S'){
x=input(),y=input();
x++,y++;
int ans=0;
rep(i,0,4){
ans+=query(1,1,n,x,y,i)*(1<<i);
}
output(ans);
}
else if(op[0]=='O'){
z=input(),x=input(),y=input();
x++,y++;
rep(i,0,4){
if(z&(1<<i)){
modefiy_or_and(1,1,n,x,y,1,i);
}
}
}
else if(op[0]=='A'){
z=input(),x=input(),y=input();
x++,y++;
rep(i,0,4){
if(!(z&(1<<i))){
modefiy_or_and(1,1,n,x,y,0,i);
}
}
}
else{
z=input(),x=input(),y=input();
x++,y++;
rep(i,0,4){
if((z&(1<<i))){
modefiy_xor(1,1,n,x,y,i);
}
}
}
}
}
return 0;
}