1. 程式人生 > >SPOJ QTREE4 Query on a tree IV (邊分治 + 堆)

SPOJ QTREE4 Query on a tree IV (邊分治 + 堆)

題意:

給定一棵樹,節點有黑白兩種顏色,有正負的邊權。

有兩種操作:

一種是修改反轉某個節點的顏色;

另一種是詢問樹上最遠的兩個白色節點的距離。

思路:

樹剖+堆維護的程式碼還是沒敢去碼。。以後再補了。。

這裡用邊分治+堆來維護。

邊分治的優點比起點分支來說,優點就是每次分治之後,只有兩個分支,處理起來比較簡單,程式碼比較好寫。缺點就是需要新增虛點,常數比較大。

邊分治就是先新增虛點,使得每個節點的度數小於等於3,新增虛點的方法很容易看懂。

邊分治就是選在當前分治結構裡面選一條邊,使得邊的兩端最大聯通塊儘可能的小。

對於一個分治結構,假設找到的分治的邊為x-y,對於這個分治結構中的路徑只有兩種,不經過邊x-y的和經過邊x-y的,前者由子分治結構來考慮,現在只考慮後者。可以對邊x-y兩端分別維護兩個大頂堆,堆裡面放的是白色節點距離x的距離或者白色節點距離y的距離。所以經過x-y的最大路徑就是兩個堆的最大值加上x-y的邊權。但是有修改操作,我們可以在堆裡面再維護一個值,就是節點號x,如果堆頂的節點是黑色的話,說明這個節點已經不能用了,要pop掉。所以對每個節點要維護它所在的每一個分治結構,並且記錄它是在分支結構的哪一邊,更新的時候要沿著分治結構自底向上更新,最後詢問的時候就是O(1),更新是O(lognlogn)。

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<set>
#include<algorithm>

using namespace std;

#define LL long long
#define eps 1e-8
#define MP make_pair
#define N 200020
#define M 400020
#define NLGN 400002
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define mod 258280327
#define inf 0x3f3f3f3f
#define pii pair<int, int>

#define ULL unsigned long long


int readint() {
    char c;
    while((c = getchar()) && !(c >= '0' && c <= '9') && c != '-');
    int ret = c - '0', sgn = 0;
    if(c == '-') sgn = 1, ret = 0;
    while((c = getchar()) && c >= '0' && c <= '9')
        ret = ret * 10 + c - '0';
    if(sgn) ret = -ret;
    return ret;
}

char buf[8000000],*pt = buf,*o = buf;
int getint(){
    int f = 1,x = 0;
    while((*pt != '-') && (*pt < '0' || *pt > '9'))    pt ++;
    if(*pt == '-')    f = -1,pt ++;    else    x = *pt++ - 48;
    while(*pt >= '0' && *pt <= '9')    x = x * 10 + *pt ++ - 48;
    return x * f;
}
char getch(){
    char ch;
    while(*pt < 'A' || *pt > 'Z')    pt ++;
    ch=*pt;pt++;
    return ch;
}

struct node {
    int x, v;
    node() {}
    node(int x, int v):x(x), v(v) {};
    bool operator < (const node &b) const {
        return v < b.v;
    }
};

struct P {
    int p, t, d;
    P() {}
    P(int p, int t, int d): p(p), t(t), d(d) {}
};

vector<P> vt[N];

vector<node> g[N];
int n, fst[N], nxt[M], vv[M], cost[M], e;
bool del[M];
int tot, cnt, sz[N];


void init() {
    memset(fst, -1, sizeof fst);
    e = 0;
}

void add(int u, int v, int c) {
    del[e] = 0, vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
    del[e] = 0, vv[e] = u, nxt[e] = fst[v], cost[e] = c, fst[v] = e++;
}
vector<node> t;
int mx[NLGN], cc[NLGN], LC[NLGN], RC[NLGN];

priority_queue<node> q[NLGN][2];
priority_queue<node> Q;

int ans;

bool col[N];

void dfs(int u, int p) {
	int fa = 0;
    for(int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].x;
        if(v == p) continue;
		if(fa == 0) {
			add(u, v, g[u][i].v);
			fa = u;
		}
		else {
			int k = ++tot;
			add(fa, k, 0);
			add(k, v, g[u][i].v);
			fa = k;
		}
        dfs(v, u);
    }


}


void dfs1(int u, int p) {
    sz[u] = 1;
    for(int i = fst[u]; ~i; i = nxt[i]) {
        int v = vv[i];
        if(v == p || del[i]) continue;
        dfs1(v, u);
        sz[u] += sz[v];
    }
}

pii dfs2(int u, int p, int tt) {
    pii ret(inf, -1);
    for(int i = fst[u]; ~i; i = nxt[i]) {
        int v = vv[i];
        if(v == p || del[i]) continue;
        int x = max(sz[v], tt - sz[v]);
        if(x < ret.first)
            ret = MP(x, i);
        pii t = dfs2(v, u, tt);
        if(t.first < ret.first)
            ret = t;
    }
    return ret;
}

void dfs3(int u, int p, int k, int t, int d) {
    if(u >= 1 && u <= n) {
        vt[u].push_back(P(k, t, d));
        q[k][t].push(node(u, d));
    }
    for(int i = fst[u]; ~i; i = nxt[i]) {
        int v = vv[i], c = cost[i];
        if(v == p || del[i]) continue;
        dfs3(v, u, k, t, d + c);
    }
}
void update(int p) {
    while(!q[p][0].empty()) {
        if(col[q[p][0].top().x]) {
            q[p][0].pop();
            continue;
        }
        break;
    }

    while(!q[p][1].empty()) {
        if(col[q[p][1].top().x]) {
            q[p][1].pop();
            continue;
        }
        break;
    }
	if(q[p][0].empty() || q[p][1].empty())
		mx[p] = 0;
	else
		mx[p] = q[p][0].top().v + q[p][1].top().v + cc[p];
	if(LC[p]) mx[p] = max(mx[p], mx[LC[p]]);
	if(LC[p]) mx[p] = max(mx[p], mx[RC[p]]);

}

int calc(int u) {
    dfs1(u, -1);
    int id = dfs2(u, -1, sz[u]).second;
    if(id == -1) return 0;

    int x = vv[id], y = vv[id^1];


    del[id] = del[id^1] = 1;

    int t = ++cnt;
    dfs3(x, -1, t, 0, 0);
    dfs3(y, -1, t, 1, 0);

    LC[t] = calc(x);
	RC[t] = calc(y);

    cc[t] = cost[id];

    ans = max(ans, mx[t]);
    update(t);
	return t;

}


int main() {

   // freopen("tt.txt", "r", stdin);


   fread(buf,1,8000000,stdin);

    while(1) {
        n = getint();
        init();
        for(int i = 1; i < n; ++i) {
            int u, v, c;
            u = getint();
            v = getint();
            c = getint();
            g[u].push_back(node(v, c));
            g[v].push_back(node(u, c));
        }
        tot = n;
        dfs(1, -1);
        ans = 0;
        calc(1);

        int qq;
        qq = getint();
        int node_cnt = n;



        while(qq--) {
            char s[10];
            int u;
            s[0] = getch();
            if(s[0] == 'A') {
                if(node_cnt == 0) {
                    puts("They have disappeared.");
                }
                else
                    printf("%d\n", max(0, mx[1]));
                continue;
            }
            u = getint();

            if(col[u]) {
                ++node_cnt;
                col[u] = 0;
                for(int i = vt[u].size() - 1; i >= 0; --i) {
                    int p = vt[u][i].p;
                    int t = vt[u][i].t;
                    int d = vt[u][i].d;
                    q[p][t].push(node(u, d));
                    update(p);
                }
            }
            else {
                --node_cnt;
                col[u] = 1;
                for(int i = vt[u].size() - 1; i >= 0; --i) {
                    int p = vt[u][i].p;
                    update(p);
                }
            }

        }
    }
    return 0;
}