1. 程式人生 > >ZOJ 1610 Count the Colors(線段樹)

ZOJ 1610 Count the Colors(線段樹)

題意:

題意:給一個區間,有n次染色操作,每次將[x1, x2]染為c,求最後每種顏色各有多少線段可以看到。

分析:

根原來稍有些不同。不過還是一般的套路。就是得注意兩個地方,一個是用tmp表示之前一段的區間顏色。另一個是當詢問操作的過程中進行到l==r的時候記得把tmp再修改回-1.

#include<bits/stdc++.h>

using namespace std;

int n,tmp;
const int maxn=8100;

int tree[maxn<<2];
int ans[maxn];

void update(int i){
    if(tree[i]==-1) return;
    tree[i<<1]=tree[i<<1|1]=tree[i];
    tree[i]=-1;
}

void change(int tl,int tr,int i,int l,int r,int c){
    if(tl>r||tr<l) return;
    if(tl<=l&&r<=tr){
        tree[i]=c;
        return ;
    }
    update(i);
    int mid=l+r>>1;
    change(tl,tr,i<<1,l,mid,c);
    change(tl,tr,i<<1|1,mid+1,r,c);
}

void query(int l,int r,int i){
    if(tree[i]!=-1){
        if(tree[i]!=tmp){
            ans[tree[i]]++;
        }
        tmp=tree[i];
        return;
    }
    if(l==r){
        tmp=-1;             //記得這塊。
        return;
    }
    int mid=l+r>>1;
    query(l,mid,i<<1);
    query(mid+1,r,i<<1|1);
}

int main(){
    while(scanf("%d",&n)!=EOF){
        memset(tree,-1,sizeof tree);
        while(n--){
            int x,y,c;
            scanf("%d%d%d",&x,&y,&c);
            change(x+1,y,1,1,8000,c);
        }
        tmp=-1;                     //tmp儲存之前一段的顏色。
        memset(ans,0,sizeof ans);
        query(1,8000,1);
        for(int i=0;i<=8000;i++){
            if(ans[i]) printf("%d %d\n",i,ans[i]);
        }
        puts("");
    }
    return 0;
}