您的位置:首页 > 产品设计 > UI/UE

SPOJ QTREE Query on a tree(边权LCT模板)

2015-08-01 11:53 661 查看
边权LCT...

一般用LCT搞边权有两种搞法,一种是类似树剖那样把边对应到点上,也就是除了根之外其他的节点都对应一条边,所以这样就不能换根,也就是不能进行树的分离和合并(好像如果LCT不能换根的话和树剖差不多了。。。);另一种是将每条边都当成一个点,然后将它的两个端点跟它连边,这样边权就转化成了点权,但是节点数多了一倍,可以实现各种操作。

#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 20020
#define M 80020
#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 ULL unsigned long long

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

int n, m;

int ch
[2], key
, pre
, rev
;
bool rt
;

int fst
, nxt[M], vv[M], e;
int val
;

int mx
;
void init() {
    for(int i = 1; i <= n + n - 1; ++i) {
        rt[i] = 1;
        fst[i] = -1;
        ch[i][0] = ch[i][1] = 0;
        pre[i] = 0;
        val[i] = 0;
        rev[i] = 0;
    }
    e = 0;
}
void add(int u, int v) {
    vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}

void dfs(int u, int p) {
    pre[u] = p;
    mx[u] = val[u];
    key[u] = val[u];
    for(int i = fst[u]; ~i; i = nxt[i]) {
        int v = vv[i];
        if(v != p)
            dfs(v, u);
    }
}

void update_rev(int x) {
    if(!x) return;
    rev[x] ^= 1;
    swap(ch[x][0], ch[x][1]);
}

void push_down(int x) {
    if(rev[x]) {
        update_rev(ch[x][0]);
        update_rev(ch[x][1]);
        rev[x] = 0;
    }
}

void push_up(int x) {
    mx[x] = key[x];
    mx[x] = max(mx[x], mx[ch[x][0]]);
    mx[x] = max(mx[x], mx[ch[x][1]]);
}

void rot(int x) {
    int y = pre[x], d = ch[y][1] == x;

    ch[y][d] = ch[x][!d];
    pre[ch[x][!d]] = y;
    pre[x] = pre[y];
    pre[y] = x;
    ch[x][!d] = y;

    if(rt[y]) rt[y] = false, rt[x] = true;
    else
        ch[pre[x]][ch[pre[x]][1]==y] = x;
    push_up(y);
}

void P(int x) {
    if(!rt[x]) P(pre[x]);
    push_down(x);
}

void splay(int x) {
    P(x);
    while(!rt[x]) {
        int f = pre[x], ff = pre[f];
        if(rt[f]) rot(x);
        else if((ch[ff][1] == f) == (ch[f][1] == x))
            rot(f), rot(x);
        else
            rot(x), rot(x);
    }
    push_up(x);
}
void Access(int x) {
    int y = 0;
    for(; x; y = x, x = pre[x]) {
        splay(x);
        rt[ch[x][1]] = true;
        ch[x][1] = y;
        rt[y] = false;
        push_up(x);
    }
}

void lca(int &u, int &v) {
    Access(v), v = 0;
    for(splay(u); pre[u]; v = u, u = pre[u], splay(u)) {
        rt[ch[u][1]] = true;
        ch[u][1] = v;
        rt[v] = false;
        push_up(u);
    }
}

void make_root(int x) {
    Access(x);
    splay(x);
    update_rev(x);
}

int query(int u, int v) {
	/*
    lca(u, v);
    int ret = key[u];
    ret = max(ret, mx[v]);
    ret = max(ret, mx[ch[u][1]]);
	*/
	make_root(u);
	Access(v);
	splay(v);
    return mx[v];
}

int main() {
    int cas;
    scanf("%d", &cas);
    while(cas--) {
        scanf("%d", &n);
        init();
        for(int i = 1; i < n; ++i) {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            add(i + n, u);
            add(u, i + n);
            add(i + n, v);
            add(v, i + n);
            val[i+n] = c;
        }
        dfs(1, 0);

        char s[10];

        while(1) {
            scanf("%s", s);
            if(s[0] == 'D') break;

            int u, v;
            scanf("%d%d", &u, &v);

            if(s[0] == 'Q') {
                make_root(u);
                Access(v);
                splay(v);
                printf("%d\n", mx[v]);
            }
            else {
                splay(u + n);
                key[u+n] = v;
                push_up(u + n);
            }
        }

    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: