poj 2777 线段树+延迟更新

 

 

题目链接:  poj 2777

 

 

题意:板块涂色,询问区间内颜色的数目。

 

 

解题:因为题目给出颜色数目最多30种,因此可以借用二进制中的或运算  来更新父区间。  但是这写的是线段树常用的懒人标记------延迟更新。

 

 

别人已经写的很好了,直接借用吧,博客链接 https://blog.csdn.net/Tong_zhi/article/details/82683219

 

言下之意就是    当遇到的区间,已经被包含   在更新区间内,  如果按照常规的思路,那么就是继续遍历到叶结点,一一进行修改,但是这样很浪费时间。

这里借用了懒标记,也就是对这种    纯区间(区间内的元素都需要更改成某值),我们只需要对他加一个标记。当下次更新或者询问的时候再进行修改。

 

修改操作:   先将自己的标记赋值给左右儿子,然后取消自己的标记,对于左右儿子的标记,也一样当下次更新或者询问的时候再进行修改。

 

 

下推操作(懒标记):

void pushdown(int rt)
{
    if (tree[rt].lazy){
        tree[rt<<1].col=tree[rt<<1|1].col=tree[rt].lazy;
        tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
        tree[rt].lazy=0;
    }
    return ;
}

 

 

AC代码:

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<map> 
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);

const int MAXN=1e5+10;
struct s{
    int l,r;
    ll col,lazy;
}tree[MAXN<<2];
int l,t,o;//长度,颜色数,询问次数
ll ans;
void btree(int rt,int l,int r)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].lazy=0;
    tree[rt].col=1;
    if (l==r){
        return ;
    }
    int mid=(l+r)>>1;
    btree(rt<<1,l,mid);
    btree(rt<<1|1,mid+1,r);
    return ;
}
void pushdown(int rt)
{
    if (tree[rt].lazy){
        tree[rt<<1].col=tree[rt<<1|1].col=tree[rt].lazy;
        tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
        tree[rt].lazy=0;
    }
    return ;
}
void update(int rt,int a,int b,int c)
{
    if (a>tree[rt].r||b<tree[rt].l){
        return ; 
    }
    else if (a<=tree[rt].l&&tree[rt].r<=b){
        tree[rt].col=tree[rt].lazy=1<<(c-1);
        return ;
    }
    pushdown(rt);
    update(rt<<1,a,b,c);
    update(rt<<1|1,a,b,c);
    tree[rt].col=tree[rt<<1].col|tree[rt<<1|1].col;
    return ;
}
void query(int rt,int a,int b)
{
     if (a>tree[rt].r||b<tree[rt].l){
         return ;
     }
     else if (a<=tree[rt].l&&tree[rt].r<=b){
         ans|=tree[rt].col;
         return ;
     }
     pushdown(rt);
     query(rt<<1,a,b);
     query(rt<<1|1,a,b);
     return ;
}
ll find(ll a)
{
    int tmp=0;
    while (a){
        if (a%2==1)
            tmp++;
        a>>=1;
    }
    return tmp;
}
int main()
{
    scanf("%d%d%d",&l,&t,&o); 
    btree(1,1,l);
    while (o--){
        char str;
        int a,b,c;
        cin>>str;
        if (str=='C'){
            scanf("%d%d%d",&a,&b,&c);
            update(1,a,b,c);
        }
        else{
            scanf("%d%d",&a,&b);
            ans=0;
            if (a>b)
                query(1,b,a);
            else    
                query(1,a,b);
            cout<<find(ans)<<endl;
        }
    }
    return 0;
}

 

posted @ 2019-07-21 14:20  生活待我如初恋  阅读(117)  评论(0编辑  收藏  举报