hdu5444Elven Postman(主席樹思想的應用)

主席樹這個概念應該不陌生吧!恩?不會, 戳這裏php

主席樹(函數式線段樹)用的是函數思想,一個節點開數組用來保存本身的左右節點,這樣節省許多沒必要要的空間,還能夠保存許多歷史狀態。而這裏咱們用的是主席樹的函數思想來實現。html

上題:http://acm.hdu.edu.cn/showproblem.php?pid=5444數組

題目大意:函數

給你一個序列,第一個數爲二叉樹根節點,以後每一個數往上加節點,且保證左節點小於根節點,且保證右節點大於根節點。且每一個節點最多有2個子節點。而後再查詢位置,每往左找輸出一個E,右找輸出W。例如序列2, 1, 4, 3能夠生成以下圖:ui

 

例如查找1,須要往左一次輸出E,查找2,不須要搜直接輸出,查找3須要向右一次再向左一次,輸出WE。spa

哇!這題好水,不就是二叉樹嗎?啪啪啪,幾分鐘碼完了, 交一發,嗯,竟然RE了,不行,的開大叔組,開成10W,嗯?又RE了。最後一想若是這個數列是1-n,即a[i] = i,那樣須要訪問到2的1000次方個節點。咕~~(╯﹏╰)b,鬱悶呢,而後回想起之前學過的主席樹,能夠開數組記錄該節點的左右兒子,那樣豈不是隻要訪問到n個節點就行。而後就這樣AC了。(比賽的時候提交的時候超了了51s,,14:00:51的時候提交的。原本能AC的,TAT)htm

附上代碼:blog

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 4000 + 5;

int a[N], b[N],ls[N], rs[N], mx[N];

int n, k, tot, sz, ql, qr, x, q, T;

void update(int o, int l, int r, int p){
    int m = (l + r) >> 1;
    if(p <= mx[o]){
        if(ls[o] == 0){
            ls[o] = tot;
            mx[tot] = p;
            return ;
        }
        else update(ls[o], l, m, p);
    }
    else {
        if(rs[o] == 0){
            rs[o] = tot;
            mx[tot] = p;
            return;
        }
        else update(rs[o], m + 1, r, p);
    }
}

void query(int o, int l, int r, int k){
    if(mx[o] == k)return ;
    int m = (l + r) >> 1;
    if(k <= mx[o]){
        printf("E");
        query(ls[o], l, m, k);
    }
    else{
        printf("W");
        query(rs[o], m + 1, r, k);
    }
}

void work(){
    scanf("%d", &x);
    query(1, 1, n, x);
    puts("");
}

int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        tot = 1;
        //Build(rt[0], 1, n);
        memset(mx, 0, sizeof(mx));
        memset(ls, 0, sizeof(ls));
        memset(rs, 0, sizeof(rs));
        //for(int i = 1; i <= n; i ++)ls[i] = i << 1, rs[i] = i << 1|1;
        //for(int i = 0; i <= 20; i ++)printf("i = %d, rt = %d, ls = %d, rs= %d, mx = %d\n", i, rt[i], ls[i], rs[i], mx[i]);
        for(int i = 1; i <= n; i ++){
            scanf("%d", a + i);
            if(i == 1)mx[1] = a[1];
            else update(1, 1, n, a[i]);
            tot ++;
        }
        scanf("%d", &q);
        while(q --)work();
    }
    return 0;
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息