poj 1436 區間線段樹 離散化

來源:互聯網
上載者:User

/*
    線段樹  擴點 擴線  區間覆蓋  好題  

    題意:給出n條平行於Y軸的線段(y', y'', x),然後3條一組,問有多少組可見線段組。“可見”的定義為,兩條線段能由一條水平先串連但不交於其它的線段。“可見線段組”的定義為該組內的3條線段兩兩可見。

    心得:之前看poj_3225,死活看不懂,跳過了。做這道題,它們的離散化方法是一樣的:線段 = 一個閉區間 + 兩個端點。而線段樹是只存點的,為瞭解決這個問題我們可以把這個閉區間也化成一個點,這樣就可以存入線段樹裡了。而線段 * 2這一方法正好可以實現這一點。如,
        區間[0,2]離散化後就變成這麼些點:
        真實的線段:          [0], (0,1), [1], (1,2), [2] ...
        化為線段樹裡對應的點: 0     1     2     3     4  ...
        

        當然也可以用poj_2528這樣的方法來做,不過就是要處理的東西多些,麻煩些。poj_2528的解法是應對區間過大時防止MLE/TLE的解法,跟這道題不一樣,這道題的重點是同化區間和點,poj_2528的重點是縮短區間的長度。
        *** 偶數點代表點,奇數代表線段,遇到有線段類的題目(用線段樹做)經常要考慮乘以2,表示浮點的線段 ***

    思路:
    
    下面摘抄自大牛們的blog:
    "能明顯的感覺到是區間覆蓋問題了。但是有一個細節問題,就是中間的水平線不一定經過整點,所以即使這個區間的所有點都被覆蓋,也不能說其就不能穿過一條線,於是,可以將所有線段的長度擴大至2倍,這樣就解決了這個問題。"
    "從左至右,一次對每條線段,先進行查詢,看左邊能看見多少條線段,然後進行覆蓋,因為很明顯,如果一條線段能看見另一條線段,那麼這個關係必然是相互的,所以對每條線段,只需要往左看就行了"
    "注意:如 範例 中 ,0 2 2,3 4 2這兩條線段,可以看到 2 3之間是沒有被覆蓋的,但是線上段樹中我們看不到這條線段,因為 變成 浮點數了,不能處理,那麼我們可以將 座標 x2,這樣就變成 4 6,中間就多出一個點 5 了,就可以判斷了。。
    偶數點代表點,奇數代表線段,遇到有線段類的題目(用線段樹做)經常要考慮乘以2,表示浮點的線段。。。poj  3225這題類似"
    "注意:由於線段包括端點,如果這條直線y=c剛好穿過某條線段的端點,則情況會變得有些麻煩.可以採用這種方法來做:將上下縱座標乘2,橫座標不變,改變原來[y,y+1)的節點儲存方式,變為[y,y]式,這樣,就可以簡單地處理端點問題,並且它對於所有情況都有很好的效果.自己畫個圖就明白了."

*/


#include <algorithm>#include <vector>#include <stdio.h>#include <string.h>using namespace std;#define     MAXN        8005#define     MAX_HIGH        8000 * 2#define     debug       printf("!\n")#define     MID(x,y)    (((x)+(y))>>1)#define     L(x)        ((x)<<1)#define     R(x)        (((x)<<1)|1)struct Line {    int x, y1, y2;} line[MAXN];struct Seg_tree_Node {    int l, r, label;} f[MAX_HIGH * 4];bool path[MAXN][MAXN];vector<int> vis[MAXN];int n;void init(){    memset(path, false, sizeof(path));    for(int i = 1; i <= n; i++) vis[i].clear();}void build(int u, int l, int r){    f[u].l = l, f[u].r = r, f[u].label = 0;    if(l == r) return ;     int mid = MID(l, r);    build(L(u), l, mid);    build(R(u), mid+1, r);}inline bool cmp(const Line & a, const Line & b){    return a.x < b.x;}void Query(int u, int l, int r, int now){    if(f[u].label == 0) return;    else if(f[u].label != -1) {        if(path[now][f[u].label]) return ;        path[now][f[u].label] = true;        vis[now].push_back(f[u].label);        return ;    }    int mid = MID(f[u].l, f[u].r);    if(r <= mid) Query(L(u), l, r, now);    else if(mid < l) Query(R(u), l, r, now);    else {        Query(L(u), l, mid, now);        Query(R(u), mid+1, r, now);    }}void push_down(int u){    f[L(u)].label = f[R(u)].label = f[u].label;    f[u].label = -1;}void Update(int u, int l, int r, int now){    if(l == f[u].l && f[u].r == r) {        f[u].label = now;        return;    }    if(f[u].label > 0) push_down(u);    f[u].label = -1;    int mid = MID(f[u].l, f[u].r);    if(r <= mid) Update(L(u), l, r, now);    else if(mid < l) Update(R(u), l, r, now);    else {        Update(L(u), l, mid, now);        Update(R(u), mid+1, r, now);    }}int calc(){    int ans = 0;    for(int x = 1; x <= n; x++)        for(int Size1 = vis[x].size(), i = 0; i < Size1; i++) {            int y = vis[x][i];            for(int Size2 = vis[y].size(), j = 0; j < Size2; j++) {                int z = vis[y][j];                if(path[x][z]) ans++;            }        }//    for(int i = 1; i <= n; i++) {//        printf("# %d : ", i);//        for(int j = 0; j < vis[i].size(); j++) printf("%d  ", vis[i][j]);//        printf("\n");//    }    return ans;   }int main(){    int cases;    scanf("%d", &cases);    while(cases--) {        scanf("%d", &n);        init();        build(1, 0, MAX_HIGH);        for(int i = 1; i <= n; i++) {            scanf("%d%d%d", &line[i].y1, &line[i].y2, &line[i].x);            line[i].y1 <<= 1;            line[i].y2 <<= 1;        }        sort(line+1, line+n+1, cmp);        for(int i = 1; i <= n; i++) {            Query(1, line[i].y1, line[i].y2, i);            Update(1, line[i].y1, line[i].y2, i);        }        printf("%d\n", calc());    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.