题目链接:传送门

 

 题意:题意很简单,两种操作,一:区间每一个数或上x,二:求区间每个数或上x的总和。 (或   ' | ')

做法:最开始我想的就是单点更新,果断队友T了,然后队友用位来储存数字,然后延迟标记区间更新就过了,虽然找了很久bug。

 

///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
#include<map>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const long long mod=1e9+7;
const int INF=0x3f3f3f3f;

int n,q,x,lazy[800000];
string u;

struct node
{
    int pos[25];
    node()
    {
        for(int i=0;i<=24;i++)
            pos[i]=0;
    }
}root[800000];

void upload(int sign)
{
    for(int i=0;i<=22;i++)
        root[sign].pos[i]=root[sign<<1].pos[i]+root[sign<<1|1].pos[i];
}

void download(int sign,int l,int r)
{
    if(lazy[sign])
    {
        int mid=l+r>>1;
        lazy[sign<<1]|=lazy[sign];
        lazy[sign<<1|1]|=lazy[sign];
        for(int i=0;i<=22;i++)
        {
            if(lazy[sign]>>i&1)
            {
                root[sign<<1].pos[i]=mid-l+1;
                root[sign<<1|1].pos[i]=r-mid;
            }
        }
        lazy[sign]=0;
    }
}

void buildroot(int l,int r,int sign)
{
    if(l==r)
    {
        scanf("%d",&x);
        for(int i=0;i<=22;i++)
            root[sign].pos[i]=x>>i&1;
        return ;
    }
    int mid=l+r>>1;
    buildroot(l,mid,sign<<1);
    buildroot(mid+1,r,sign<<1|1);
    upload(sign);
}

void updateroot(int l,int r,int sign,int a,int b,int c)
{
    if(a==l&&r==b)
    {
        lazy[sign]|=c;
        for(int i=0;i<=22;i++)
        {
            if(lazy[sign]>>i&1)
                root[sign].pos[i]=r-l+1;
        }
        return ;
    }
    download(sign,l,r);
    int mid=l+r>>1;
    if(b<=mid)
        updateroot(l,mid,sign<<1,a,b,c);
    else if(a>mid)
        updateroot(mid+1,r,sign<<1|1,a,b,c);
    else
    {
        updateroot(l,mid,sign<<1,a,mid,c);
        updateroot(mid+1,r,sign<<1|1,mid+1,b,c);
    }
    upload(sign);
}

ll findroot(int l,int r,int sign,int a,int b)
{
    if(a==l&&r==b)
    {
        ll ans=0;
        for(int i=0;i<=22;i++)
            ans+=(root[sign].pos[i]*(1LL<<i));
        return ans;
    }
    download(sign,l,r);
    int mid=l+r>>1;
    ll ans=0;
    if(b<=mid)
        ans+=findroot(l,mid,sign<<1,a,b);
    else if(a>mid)
        ans+=findroot(mid+1,r,sign<<1|1,a,b);
    else
    {
        ans+=findroot(l,mid,sign<<1,a,mid);
        ans+=findroot(mid+1,r,sign<<1|1,mid+1,b);
    }
    return ans;
}

int main()
{
    MT(lazy,0);
    scanf("%d %d",&n,&q);
    buildroot(1,n,1);
    while(q--)
    {
        cin>>u;
        if(u=="SUM")
        {
            int a,b;
            scanf("%d %d",&a,&b);
            printf("%lld\n",findroot(1,n,1,a,b));
        }
        else
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c); 
            updateroot(1,n,1,a,b,c);
        }
    }
    return 0;
}