FZU 2105 Digits Count

 Problem 2105 Digits Count

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

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.



因为数值得范围<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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值