1. 程式人生 > >HDU1540--線段樹(最長連續區間)

HDU1540--線段樹(最長連續區間)

這個題目好像不是很難,可是我想了很久,還超時了。。我用的是普通線段樹和二分,第一次用二分超時啊啊啊啊啊

好,讓我們言歸正傳。(參考別的大佬的做法,賊6)

看到這個題目之後,能夠想到它是為了求包含一個點的最大連續區間。那麼多的區間,應該是要用線段樹來做。

可以想得到,查詢的時候,是從這個點展開,判斷左右是否連續。

首先,我們用遞迴查詢到這個點,或者說是包含這個點的連續區間,假設它是一個左子樹,那我們就要加上它相鄰的右子樹的從左邊開始的連續區間,如果它是右子樹,那麼就按相反。

這樣的話,我們不如就建立兩個陣列,一個是從左邊開始累加區間長度的陣列(lsum[]),一個是從右邊開始累加區間長度的陣列(rsum[])

,然後建樹,更新節點,查詢。

還要提一點,由於題目中有一個什麼重建,emmm,就是先進後出的棧嘛,所以我們這裡就可以用到c++中的一個stack容器

有這幾個常用的操作吧:

stack<int> s;

1.入棧:如s.push(x);

2.出棧:如 s.pop().注意:出棧操作只是刪除棧頂的元素,並不返回該元素。

3.訪問棧頂:如s.top();

4.判斷棧空:如s.empty().當棧空時返回true。

5.訪問棧中的元素個數,如s.size();

貼程式碼:

#include"cstdio"
#include"stack"
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 50010

int lsum[4*maxn],rsum[4*maxn],flag;
void Build(int l,int r,int rt) {
    lsum[rt] = rsum[rt] = r-l+1;
    if (l == r) return;
    int m = (l+r) >> 1;
    Build(lson);
    Build(rson);
}
void Pushup(int rt,int m) {
    lsum[rt] = lsum[rt<<1];
    rsum[rt] = rsum[rt<<1|1];
    if (lsum[rt] == m - (m>>1)) lsum[rt] += lsum[rt<<1|1];//yi cuo
    if (rsum[rt] == m>>1) rsum[rt] += rsum[rt<<1];
}
void Updata(int p,int x,int l,int r,int rt) {
    if (l == r) {
        lsum[rt] = rsum[rt] = x;
        return;
    }
    int m = (l+r) >> 1;
    if (p <= m) Updata(p,x,lson); else Updata(p,x,rson);
    Pushup(rt,r-l+1);
}
int Query(int p,int l,int r,int rt) {
    if (rsum[rt] >= r-p+1) {
        flag = 1;
        return rsum[rt];
    }
    if (lsum[rt] >= p-l+1) {
        flag = 1;
        return lsum[rt];
    }
    if (l == r) return 0;
    int m = (l+r) >> 1, t = 0;
    if (p > m) {
        t = Query(p,rson);
        if (flag) {
            flag = 0;
            t += rsum[rt<<1];
        }
    } else {
        t = Query(p,lson);
        if (flag) {
            flag = 0;
            t += lsum[rt<<1|1];
        }
    }
    return t;
}
int main() {
    int n,m;
//    freopen("1.in","r",stdin);
    while(~scanf("%d%d",&n,&m)) {
        Build(1,n,1);
        char cmd[2];
        stack<int> sta;
        for (int i = 0;i < m;i ++) {
            scanf("%s",cmd);
            if (cmd[0] == 'D') {
                int x;
                scanf("%d",&x);
                sta.push(x);
                Updata(sta.top(),0,1,n,1);
            } else
            if (cmd[0] == 'Q') {
                int x;
                flag = 0;
                scanf("%d",&x);
                printf("%d\n",Query(x,1,n,1));
            } else {
                Updata(sta.top(),1,1,n,1);
                sta.pop();
            }
        }
    }
    return 0;
}