POJ2528線段樹區間合併加離散化

POJ2528Mayor’s posters就只支持一種操作,一次性的給一段區間塗上顏色,且每次顏色均不一樣。問最後一共可以看到多少種顏色。
關於線段樹的更詳細實現請參考線段樹解決區間問題包括延遲操作以及離散化

/*
    在數軸上,一次給一個線段塗上顏色
    後面的顏色會覆蓋前面的顏色
    問最後能看到多少個顏色

    顯然是成段更新,線段樹
    區間範圍是1千萬,需要離散化
    另外注意位置編號的含義
*/

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <numeric>
using namespace std;

int const SIZE = 20010;

inline int lson(int x){return x<<1;}
inline int rson(int x){return lson(x)|1;}

int ST[SIZE<<2];//段數
int L[SIZE<<2],R[SIZE<<2];//左右邊界的顏色
int Lazy[SIZE<<2];

struct _t{
    int cnt;
    int left;
    int right;
    _t(int aa=0,int bb=0,int cc=0):cnt(aa),left(bb),right(cc){}
};

inline void _pushUp(int t){
    ST[t] = ST[lson(t)] + ST[rson(t)] + (R[lson(t)]==L[rson(t)]?-1:0);
    L[t] = L[lson(t)];
    R[t] = R[rson(t)];
}

inline void _pushDown(int t){
    if ( Lazy[t] ){
        ST[lson(t)] = ST[rson(t)] = 1;
        Lazy[lson(t)] = L[lson(t)] = R[lson(t)] = Lazy[t];
        Lazy[rson(t)] = L[rson(t)] = R[rson(t)] = Lazy[t];
        Lazy[t] = 0;
    }
}

_t query(int t,int s,int e,int a,int b){
    if ( a <= s && e <= b ){
        return _t(ST[t],L[t],R[t]);
    }

    _pushDown(t);
    int mid = (s+e) >> 1;
    _t lans,rans;
    if ( a <= mid ) {
        lans = query(lson(t),s,mid,a,b);
        if ( b <= mid ) return lans;
    }
    if ( mid < b ){
        rans = query(rson(t),mid+1,e,a,b);
        if ( mid < a ) return rans;
    }
    return _t(lans.cnt+rans.cnt+(lans.right==rans.left?-1:0),lans.left,rans.right);
}

void modify(int t,int s,int e,int a,int b,int color){
    if ( a <= s && e <= b ){
        ST[t] = 1;
        Lazy[t] = L[t] = R[t] = color;
        return;
    }

    _pushDown(t);//?
    int mid = ( s + e ) >> 1;
    if ( a <= mid ) modify(lson(t),s,mid,a,b,color);
    if ( mid < b ) modify(rson(t),mid+1,e,a,b,color);
    _pushUp(t);
}

int getUnsigned(){
	char ch = getchar();
	while( ch < '0' || ch > '9' ) ch = getchar();

	int ret = (int)(ch-'0');
	while( '0' <= ( ch = getchar() ) && ch <= '9' ) ret = ret * 10 + (int)(ch-'0');
	return ret;
}

int N,NN;
int T[SIZE];
int A[SIZE],B[SIZE];

bool read(){
    N = getUnsigned();
    for(int i=0;i<N;++i) T[i+i] = A[i] = getUnsigned(), T[i+i+1] = B[i] = getUnsigned() + 1;

    sort(T,T+N+N);
    NN = unique(T,T+N+N) - T;

    fill(ST,ST+NN*4,0);
    fill(Lazy,Lazy+NN*4,0);
    fill(L,L+NN*4,0);
    fill(R,R+NN*4,0);

    return true;
}

int Flag[SIZE];
int main(){
    //freopen("1.txt","r",stdin);

    int nofkase = getUnsigned();
    while(nofkase--){
        read();

        //成段更新
        for(int i=0;i<N;++i){
            int a = lower_bound(T,T+NN,A[i]) - T + 1;
            int b = lower_bound(T,T+NN,B[i]) - T;//左閉右開,就不用加1了
            modify(1,1,NN,a,b,i+1);
        }

        //檢查結果
        fill(Flag,Flag+N+1,0);
        int cnt = 0;
        for(int i=1;i<=NN;++i){
            _t ans = query(1,1,NN,1,i);

            if ( ans.cnt > cnt && ans.right != 0 ){
                cnt = ans.cnt;
                Flag[ans.right] = 1;
            }
        }

        printf("%d\n",accumulate(Flag+1,Flag+N+1,0));
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章