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

来源:互联网 发布:淘宝首页轮播图片尺寸 编辑:程序博客网 时间:2024/06/03 21:17

题意:

给定一棵树,节点有黑白两种颜色,有正负的边权。

有两种操作:

一种是修改反转某个节点的颜色;

另一种是询问树上最远的两个白色节点的距离。


思路:

树剖+堆维护的代码还是没敢去码。。以后再补了。。

这里用边分治+堆来维护。

边分治的优点比起点分支来说,优点就是每次分治之后,只有两个分支,处理起来比较简单,代码比较好写。缺点就是需要添加虚点,常数比较大。


边分治就是先添加虚点,使得每个节点的度数小于等于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 longint 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;elsemx[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;}



1 0
原创粉丝点击