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

来源:互联网 发布:linux开机自动启动 编辑:程序博客网 时间:2024/05/11 13:40

边权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 longint 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[N][2], key[N], pre[N], rev[N];bool rt[N];int fst[N], nxt[M], vv[M], e;int val[N];int mx[N];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;}


0 0
原创粉丝点击