1. 程式人生 > >poj2528 - Mayor's posters - 線段樹離散化(詳解)

poj2528 - Mayor's posters - 線段樹離散化(詳解)

Mayor's posters

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 79035   Accepted: 22736

Description

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules:

  • Every candidate can place exactly one poster on the wall.
  • All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown).
  • The wall is divided into segments and the width of each segment is one byte.
  • Each poster must completely cover a contiguous number of wall segments.


They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall.

Input

The first line of input contains a number c giving the number of cases that follow. The first line of data for a single case contains number 1 <= n <= 10000. The subsequent n lines describe the posters in the order in which they were placed. The i-th line among the n lines contains two integer numbers li and ri which are the number of the wall segment occupied by the left end and the right end of the i-th poster, respectively. We know that for each 1 <= i <= n, 1 <= li <= ri <= 10000000. After the i-th poster is placed, it entirely covers all wall segments numbered li, li+1 ,... , ri.

Output

For each input data set print the number of visible posters after all the posters are placed.

The picture below illustrates the case of the sample input.

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4

Source

Alberta Collegiate Programming Contest 2003.10.18

思路:

離散化

可以看出他給的1e+7的區間範圍太大了,硬剛的話就是tle或者mle,所以用到了離散化的思想,具體步驟如下:

把左右端點入隊,排序後去重,然後在數組裡找到大於等於左右端點的第一個值,返回它的位置,作為它的新的區間範圍,程式碼如下:

int k=0;
for(int i=1;i<=n;i++){
    scanf("d%d",&left[i],&right[i]);
    v[k++]=left[i];
    v[k++]=right[i];
}
sort(v,v+k);
int n=unique(v,v+k)-v;//表示新陣列大小,如果用vector不可以-v這樣寫
for(int i-1;i<=n;i++){
    int L=lower_bound(v,v+n,left[i])-v+1;//如果指標在v[0]的位置,-v後得0,加1表示左端點是1
    int R=lower_bound(v,v+n,right[i])-v+1;
}

比如[1,200],[50,80],[80,250]

先入隊:1,200,50,80,80,250

排序:1,50,80,80,200,250

去重:1,50,80,200,250

這時候重新判斷區間的範圍:

[1,200]=》[1,4]

[50,80]=》[2,3]

[80,250]=》[3,5]

解題思路

這個題每次張貼一張海報,新的覆蓋舊的,問最後又多少張海報會露出來,可見沒法用線段樹的push_up操作,我們在染色時,就是讓線段樹中對應一個區間的節點做一個顏色標記,然後push_bown,向下染色,查詢的時候,用hash的思想,我開了一個use陣列來表示這個顏色計算過沒有,我們查詢的是整個區間,所以在查詢的過程中,如果一個節點的顏色沒有被計算進去,則ans++,這時候use[color]=1,標記這個顏色計算過,將不再重複計算。

注意

區間範圍啊啊啊,因為區間範圍wa了N次,(我也納悶為啥不是re而是wa),我們用離散化的時候,最悲觀的情況是輸入的2*N個區間端點沒有一個重複的,那麼就相當於點是2*N個,所以陣列範圍有在2*N*4也就是N<<3

程式碼如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N=10010;
int aa[N],bb[N],ans;
int tree[N<<3],use[N<<3];
int v[2*N];

void push_down(int rt){
    if(tree[rt]!=-1){
        tree[rt<<1]=tree[rt<<1|1]=tree[rt];
        tree[rt]=-1;
    }
}
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l&&R>=r){
        tree[rt]=c;
        return ;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,lson);
    if(R>m)update(L,R,c,rson);
}

void query(int l,int r,int rt){
    if(tree[rt]!=-1){
        if(!use[tree[rt]])ans++;
        use[tree[rt]]=1;
        return ;
    }
    int m=(l+r)>>1;
    push_down(rt);
    query(lson);
    query(rson);
}

int main(){
    int t,m;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&m);
        int k=0;
        memset(v,0,sizeof(v));
        for(int i=0;i<m;i++){
            scanf("%d%d",&aa[i],&bb[i]);
            v[k++]=aa[i];
            v[k++]=bb[i];
        }
        sort(v,v+k);
        int n=unique(v,v+k)-v;
        memset(tree,-1,sizeof(tree));
        for(int i=0;i<m;i++){
            int L=lower_bound(v,v+n,aa[i])-v;
            int R=lower_bound(v,v+n,bb[i])-v;
            update(L,R,i,0,n-1,1);
        }
        ans=0;
        memset(use,0,sizeof(use));
        query(0,n-1,1);
        printf("%d\n",ans);
    }
}