zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    PAT 1088. Rational Arithmetic
    PAT 1087. All Roads Lead to Rome
    PAT 1086. Tree Traversals Again
    PAT 1085. Perfect Sequence
    PAT 1084. Broken Keyboard
    PAT 1083. List Grades
    PAT 1082. Read Number in Chinese
    求最大公因数
    [转载]Latex文件转成pdf后的字体嵌入问题的解决
    [转载]Matlab有用的小工具小技巧
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10786156.html
Copyright © 2011-2022 走看看