SPOJ QTREE5Query on a tree V(边分治)

来源:互联网 发布:len在vb中什么意思 编辑:程序博客网 时间:2024/06/05 17:06

和QTREE4的差不多

#include <bits/stdc++.h>#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;#pragma comment(linxer, "/STACK:102400000,102400000")#define LL long long #define pii pair<int, int>#define MP make_pair#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 1000000007#define inf 0x3f3f3f3f#define N 200010#define M 4000020int fst[N], vv[M], nxt[M], cost[M], e;int f[N], rt, edg, C[N];int sz[N], tim, tot, mx[N];int col[N], fa[N], lc[N], rc[N];int x[N], cx;bool vis[M];priority_queue<int> q1[N], q2[N];void init(){    memset(fst, -1, sizeof fst); e = 0;    memset(f, -1, sizeof f);}void _add(int u, int v, int c){    vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;}void add(int u, int v, int c){    vv[e] = v, nxt[e] = f[u], cost[e] = c, f[u] = e++;}void dfsS(int u, int p){    sz[u] = 1;    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i];        if(v == p || vis[i]) continue;        dfsS(v, u);        sz[u] += sz[v];    }}void dfsE(int u, int p, int d){    add(u, tim, d);    x[cx++] = d;    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i], c = cost[i];        if(v == p || vis[i]) continue;        mx[v] = max(sz[v], tot - sz[v]);        if(rt == -1 || mx[v] < mx[rt])            rt = v, edg = i, C[tim] = c;        dfsE(v, u, d + c);    }}pii find_edge(int u){    dfsS(u, -1);    tot = sz[u], rt = -1, edg = -1, cx = 0;    dfsE(u, -1, 0);    //for(int i = 0; i < cx; ++i)    //  q2[tim].push(x[i]);    return MP(rt, edg);}void solve(int u){    ++tim;    pii ee = find_edge(u);    if(ee.first == -1){        return ;    }    int i = ee.second, u1 = vv[i], u2 = vv[i^1];    vis[i] = vis[i^1] = 1;    int cur = tim;    lc[cur] = tim + 1;    fa[tim+1] = cur;    solve(u1);    rc[cur] = tim + 1;    fa[tim+1] = cur;    solve(u2);}int top(int k){    while(1){        if(q1[k].empty()) return -inf;        if(q2[k].empty()) return q1[k].top();        if(q1[k].top() == q2[k].top())            q1[k].pop(), q2[k].pop();        else return q1[k].top();    }}void gao(int u){    for(int i = f[u]; ~i; i = nxt[i]){        int v = vv[i], d = cost[i];        if(col[u]) q1[v].push(d);        else q2[v].push(d);    }}int find(int u, int son){    for(int i = f[u]; ~i; i = nxt[i]){        int v = vv[i], d = cost[i];        if(v == son){        //  printf("%d\n", d);            return d;        }    }    return -inf;}void query(int u){    int ans = -inf;    for(int i = f[u]; ~i; i = nxt[i]){        int v = vv[i], d = cost[i];        /*           if(lc[v] && rc[v]){            printf("%d %d %d %d %d\n",v, lc[v], rc[v], top(lc[v]), top(rc[v]));            ans = max(ans, top(rc[v]) + C[v] + find(u, lc[v]));            ans = max(ans, top(lc[v]) + C[v] + find(u, rc[v]));        }        */        if(fa[v]){            int son  = lc[fa[v]] == v ? rc[fa[v]] : lc[fa[v]];            ans = max(ans, top(son) - 1 + d);        }    }    printf("%d\n", -ans);}int main(){    int n;    scanf("%d", &n);    init();    for(int i = 1; i < n; ++i){        int u, v;        scanf("%d%d", &u, &v);        _add(u, v, -1);        _add(v, u, -1);    }    tim = 0;    solve(1);    int q, white = 0;    scanf("%d", &q);    while(q--){        int op, u;        scanf("%d%d", &op, &u);        if(op == 0){            col[u] ^= 1;            if(col[u]) white++;            else white--;            gao(u);        }        else{            if(white == 0)                puts("-1");            else if(col[u])                puts("0");            else                query(u);        }    }    return 0;}
0 0