1. 程式人生 > 實用技巧 >線段樹離散化+區間修改 - POJ 2528 - Mayor's posters

線段樹離散化+區間修改 - POJ 2528 - Mayor's posters

POJ - 2528 - Mayor's posters

這一題的資料範圍為1e7,由於題目資訊並沒有告訴我們最多有多少個不同的端點值,我們即使離散化處理端點也無法確定陣列長度到底能夠降到多少,因此本題只能老老實實開1e7<<2的陣列.

但是本題離散化處理仍是有必要的,離散化處理可以大大降低時間複雜度(陣列越長,update,query的遞迴層數越多)

另外,本題只需要維護一個lazy標記數字即可,沒必要額外開一個tree陣列,最終查詢所有長度為1的區間(即[i,i])對應的不同的lazy值個數即為最終答案.

#include <cstdio>
#include <vector>
#include <algorithm>
#include <set>
#include <cstdlib>

using namespace std;
#define N 10000000+2
#define MAX(a,b) (a>b?a:b)
int lazy[N<<2];
set<int> ans_set;
void push_down(int left,int right,int root){
    if(lazy[root]){
        int left_root = root<<1;
        int right_root = root<<1|1;
        lazy[left_root] = lazy[root];
        lazy[right_root] = lazy[root];
        lazy[root] = 0;
    }
}
void update(int left,int right,int root,int update_left,int update_right,int new_val){
    if(update_left <= left && update_right >= right){
        lazy[root] = new_val;
    }else{
        push_down(left,right,root);
        int mid = (left+right)>>1;
        int left_root = root<<1;
        int right_root = root<<1|1;
        if(update_left <= mid){
            update(left,mid,left_root,update_left,update_right,new_val);
        }
        if(update_right > mid){
            update(mid+1,right,right_root,update_left,update_right,new_val);
        }
    }
}

void query_all(int left,int right,int root){
    if(left == right){
        if(lazy[root])
            ans_set.insert(lazy[root]);
        return; // 最後只需要看lazy個數
    }else{
        push_down(left,right,root);
        int mid = (left+right)>>1;
        query_all(left,mid,root<<1);
        query_all(mid+1,right,root<<1|1);
    }
}
typedef pair<int,int> pii;
int binarySearch(int head,int tail,int val,const vector<int>& vec){
    int ans = 0;
    while(head <= tail){
        int mid = (head+tail)>>1;
        if(vec[mid] > val){
            tail = mid - 1;
        }else if(vec[mid] < val){
            head = mid + 1;
        }else{
            ans = mid;
            break;
        }
    }
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int q;
        int l,r;
        int maxn = 0;
        scanf("%d",&q);
        vector<pii> vec;
        set<int> st;
        for(int i = 0; i < q; i++){
            scanf("%d%d",&l,&r);
            vec.push_back(make_pair(l,r));
            st.insert(l);
            st.insert(r);
        }

        vector<int> ord;
        for(set<int> :: iterator it = st.begin(); it != st.end(); it++){
            ord.push_back(*it);
        }

        int g = ord.size();
        for(int i = 0; i < q; i++){
            vec[i].first = binarySearch(0,g-1,vec[i].first,ord) + 1;
            vec[i].second = binarySearch(0,g-1,vec[i].second,ord) + 1;
            maxn = MAX(maxn,vec[i].second);
        }

        for(int i = 0; i < q; i++){
            update(1,maxn,1,vec[i].first,vec[i].second,i+1);
        }

        query_all(1,maxn,1);
        printf("%d\n",ans_set.size());
        ans_set.clear();
    }
    system("pause");
    return 0;
}