2018湘潭大学程序设计竞赛 H (线段树,位运算区间更新,lazy)

题目:https://www.nowcoder.com/acm/contest/105/H

思路:

和poj2777非常类似,只不过它是某一区间变为某颜色,这里是某一区间加上某颜色。

还是可以用sum的某一位来表示有没有这个颜色,然后lazy标记,按位或传递下去。

#include 
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define ll long long int
using namespace std;
const int maxn=1e5+10;

int n,m;
struct node{
    int l,r;
    ll sum;
}t[maxn<<2];
ll lazy[maxn<<2];

void down(int rt){
    if(lazy[rt]){
        ll tmp=lazy[rt];
        lazy[rt<<1]|=tmp,lazy[rt<<1|1]|=tmp;
        t[rt<<1].sum|=tmp,t[rt<<1|1].sum|=tmp;
        lazy[rt]=0;
    }
}

void build(int rt,int l,int r){
    t[rt].l=l,t[rt].r=r;
    t[rt].sum=0,lazy[rt]=0;
    if(l==r){
        return ;
    }
    int mid=(l+r)>>1;
    build(lson),build(rson);
}

void update(int rt,int l,int r,int k){
    if(l<=t[rt].l&&r>=t[rt].r){
        lazy[rt]|=1ll<>1;
    if(l<=mid) update(rt<<1,l,r,k);
    if(r>mid) update(rt<<1|1,l,r,k);
    t[rt].sum=t[rt<<1].sum | t[rt<<1|1].sum;
}

ll query(int rt,int l,int r){
    if(l<=t[rt].l&&r>=t[rt].r) return t[rt].sum;
    down(rt);
    int mid=(t[rt].l+t[rt].r)>>1;
    ll ans=0;
    if(l<=mid) ans|=query(rt<<1,l,r);
    if(r>mid) ans|=query(rt<<1|1,l,r);
    return ans;
}

int main(){
    while(scanf("%d%d",&n,&m)==2){
        build(1,1,n);
        while(m--){
            int f,l,r,k;
            scanf("%d",&f);
            if(f==1){
                scanf("%d%d%d",&l,&r,&k);
                update(1,l,r,k);
            }
            else{
                scanf("%d%d",&l,&r);
                ll ans=query(1,l,r);
                int cnt=0;
                while(ans){
                    if(ans&1)
                        cnt++;
                    ans>>=1;
                }
                printf("%d\n",cnt);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(线段树)