• poj2777(线段树)


    题目链接:https://vjudge.net/problem/POJ-2777

    题意:有L块连续的板子,每块板子最多染一种颜色,有T种(<=30)颜色,刚开始将所有板子染成颜色1,O次操作(包括将[a,b]染成颜色k,和询问[a,b]的不同颜色数),输出每次询问的值。

    思路:典型的线段树的题目。用线段树实现表示一段区间的颜色值。线段树结点的属性包括l(区间左端点),r(区间右端点),value(区间的颜色值,1..T表示对应的颜色,0表示多种颜色),lazy(懒惰标记,如果不用lazy直接用value同时表示颜色值和懒惰标记会超时,因为将value作为懒惰标记时下放操作会将value置0,每次query几乎都要访问到每个叶子结点,复杂度为O(n),整个程序复杂度为(O^2))。每次query可以通过vis数组保存颜色i是否出现并由此记录不同颜色数,起始这里颜色数<=30就可以用二进制的为来表示颜色,不过用vis数组也不会超时,就懒得写进制方法了。

    AC代码:

    #include<cstdio>
    using namespace std;
    const int maxn=100005;
    
    struct node{
        int l,r,value,lazy;
    }tr[maxn<<2];
    
    int L,T,O,vis[35],ans;
    char c;
    
    void build(int v,int l,int r){
        tr[v].l=l,tr[v].r=r;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(v<<1,l,mid);
        build(v<<1|1,mid+1,r);
    }
    
    void pushdown(int v){
        tr[v<<1].value=tr[v<<1].lazy=tr[v].lazy;
        tr[v<<1|1].value=tr[v<<1|1].lazy=tr[v].lazy;
        tr[v].lazy=0;
    }
    
    void update(int v,int l,int r,int k){
        if(l<=tr[v].l&&r>=tr[v].r){
            tr[v].value=tr[v].lazy=k;
            return;
        }
        if(tr[v].lazy) pushdown(v);
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) update(v<<1,l,r,k);
        if(r>mid) update(v<<1|1,l,r,k);
        if(tr[v<<1].value==tr[v<<1|1].value)
            tr[v].value=tr[v<<1].value;
        else
            tr[v].value=0;
    }
    
    void query(int v,int l,int r){
        if(l<=tr[v].l&&r>=tr[v].r&&tr[v].value){
            if(!vis[tr[v].value]){
                ++ans;
                vis[tr[v].value]=1;
            }
            return;
        }
        if(tr[v].lazy) pushdown(v);
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) query(v<<1,l,r);
        if(r>mid) query(v<<1|1,l,r);
        if(tr[v<<1].value==tr[v<<1|1].value)
            tr[v].value=tr[v<<1].value;
        else
            tr[v].value=0;
    }
    
    int main(){
        scanf("%d%d%d",&L,&T,&O);
        build(1,1,L);
        update(1,1,L,1);
        while(O--){
            scanf(" %c",&c);
            int a,b,k;
            if(c=='C'){
                scanf("%d%d%d",&a,&b,&k);
                if(a>b){
                    int t=a;a=b,b=t;
                }
                update(1,a,b,k);
            }
            else{
                scanf("%d%d",&a,&b);
                if(a>b){
                    int t=a;a=b,b=t;
                }
                ans=0;
                for(int i=1;i<=T;++i)
                    vis[i]=0;
                query(1,a,b);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    css一div内文字居中
    (三)maven出错记录
    (二)在eclipse中使用maven
    单点登录原理及实现sso
    java定时器2-spring实现
    内存溢出
    IDE配置jvm参数
    CheckStyle
    表单提交数据量大于2m,java 后台接受不到表单传递过来的数据
    JVM实用参数(一)JVM类型以及编译器模式
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10786156.html
Copyright © 2020-2023  润新知