SPOJ QTREE2 lct

来源:互联网 发布:ember.js入门教程 编辑:程序博客网 时间:2024/05/19 20:49

题目链接
题意:
给一棵树,有边权
1、询问路径的边权和
2、询问沿着路径的第k个点标。
思路:lct裸题。

#include <iostream>#include <fstream>#include <string>#include <time.h>#include <vector>#include <map>#include <queue>#include <algorithm>#include <stack>#include <cstring>#include <cmath>#include <set>#include <vector>using namespace std;template <class T>inline bool rd(T &ret) {    char c; int sgn;    if (c = getchar(), c == EOF) return 0;    while (c != '-' && (c<'0' || c>'9')) c = getchar();    sgn = (c == '-') ? -1 : 1;    ret = (c == '-') ? 0 : (c - '0');    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');    ret *= sgn;    return 1;}template <class T>inline void pt(T x) {    if (x <0) {        putchar('-');        x = -x;    }    if (x>9) pt(x / 10);    putchar(x % 10 + '0');}typedef long long ll;typedef pair<int, int> pii;const int N = 30005;const int inf = 10000000;struct Node *null;struct Node{    Node *fa, *ch[2];    int size;    int val, ma, sum, id;    bool rev;    inline void put(){        printf("%d:id, %d,%d,%d (%d,%d) fa:%d \n", id, val, ma, sum, ch[0]->id, ch[1]->id, fa->id);    }    void debug(Node *x){        if (x == null)return;        x->put();        if (x->ch[0] != null)putchar('L'), debug(x->ch[0]);        if (x->ch[1] != null)putchar('r'), debug(x->ch[1]);    }    inline void clear(int _val, int _id){        fa = ch[0] = ch[1] = null;        size = 1;        rev = 0;        id = _id;        val = ma = sum = _val;    }    inline void add_val(int _val){        val += _val;        sum += _val;        ma = max(ma, val);    }    inline void push_up(){        size = 1 + ch[0]->size + ch[1]->size;        sum = ma = val;        if (ch[0] != null) {            sum += ch[0]->sum;             ma = max(ma, ch[0]->ma);        }        if (ch[1] != null){            sum += ch[1]->sum;            ma = max(ma, ch[1]->ma);        }    }    inline void push_down(){        if (rev){            flip(); ch[0]->rev ^= 1; ch[1]->rev ^= 1;        }    }    inline void setc(Node *p, int d){        ch[d] = p;        p->fa = this;    }    inline bool d(){        return fa->ch[1] == this;    }    inline bool isroot(){        return fa == null || fa->ch[0] != this && fa->ch[1] != this;    }    inline void flip(){        if (this == null)return;        swap(ch[0], ch[1]);        rev ^= 1;    }    inline void go(){//从链头开始更新到this        if (!isroot())fa->go();        push_down();    }    inline void rot(){        Node *f = fa, *ff = fa->fa;        int c = d(), cc = fa->d();        f->setc(ch[!c], c);        this->setc(f, !c);        if (ff->ch[cc] == f)ff->setc(this, cc);        else this->fa = ff;        f->push_up();    }    inline Node*splay(){        go();        while (!isroot()){            if (!fa->isroot())                d() == fa->d() ? fa->rot() : rot();            rot();        }        push_up();        return this;    }    inline Node* access(){//access后this就是到根的一条splay,并且this已经是这个splay的根了        for (Node *p = this, *q = null; p != null; q = p, p = p->fa){            p->splay()->setc(q, 1);            p->push_up();        }        return splay();    }    inline Node* find_root(){        Node *x;        for (x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);        return x;    }    void make_root(){        access()->flip();    }    void cut(){//把这个点的子树脱离出去        access();        ch[0]->fa = null;        ch[0] = null;        push_up();    }    void cut(Node *x){        if (this == x || find_root() != x->find_root())return;        else {            x->make_root();            cut();        }    }    void link(Node *x){        if (find_root() == x->find_root())return;        else {            make_root(); fa = x;        }    }};Node pool[N], *tail;Node *node[N], *ee[N];int n, q;void debug(Node *x){    if (x == null)return;    x->put();    debug(x->ch[0]);    debug(x->ch[1]);}inline int ask(Node *x, Node *y){    x->access();//  for (int i = 1; i <= n; i++)debug(node[i]), putchar('\n');    for (x = null; y != null; x = y, y = y->fa){        y->splay();//      for (int i = 1; i <= n; i++)debug(node[i]), putchar('\n');        if (y->fa == null)return y->ch[1]->sum + x->sum;        y->setc(x, 1);          y->push_up();    }}inline Node* get_kth(Node *x, int k){    while (x->ch[0]->size + 1 != k){        if (x->ch[0]->size >= k)            x = x->ch[0];        else k -= x->ch[0]->size + 1, x = x->ch[1];    }    return x;}inline int query_kth(Node *x, Node *y, int k){    x->access();    for (x = null; y != null; x = y, y = y->fa){        y->splay();        if (y->fa == null){            if (k == y->ch[1]->size + 1)return y->id;            if (k < y->ch[1]->size + 1)return get_kth(y->ch[1], y->ch[1]->size - k + 1)->id;            return get_kth(x, k - y->ch[1]->size - 1)->id;        }        y->setc(x, 1);        y->push_up();    }}struct Edge{    int from, to, dis, id, nex;}edge[N << 1];int head[N], edgenum;void add(int u, int v, int dis, int id){    Edge E = { u, v, dis, id, head[u] };    edge[edgenum] = E;    head[u] = edgenum++;}bool vis[N];void bfs(){    fill(vis + 1, vis + 1 + n, false);    queue<int>q;    q.push(1);    vis[1] = true;    while (!q.empty()){        int u = q.front(); q.pop();        for (int i = head[u]; ~i; i = edge[i].nex){            int v = edge[i].to;            if (vis[v])continue;            vis[v] = true;            q.push(v);            ee[edge[i].id] = node[v];            node[v]->val = edge[i].dis;            node[v]->push_up();            node[v]->fa = node[u];        }    }}int main(){    int T; rd(T);    while (T--){        rd(n);        fill(head + 1, head + n + 1, -1); edgenum = 0;        tail = pool;        null = tail++;        null->clear(-inf, 0);        null->size = 0; null->sum = 0;        for (int i = 1; i <= n; i++) {            node[i] = tail++;            node[i]->clear(0, i);        }        for (int i = 1, u, v, d; i < n; i++){            rd(u); rd(v); rd(d);            add(u, v, d, i);             add(v, u, d, i);        }        bfs();        char str[10]; int u, v, k;        while (true){            scanf("%s", str);            if (str[1] == 'O')break;            rd(u); rd(v);            if (str[0] == 'D')pt(ask(node[u], node[v])), putchar('\n');            else {                rd(k);                pt(query_kth(node[u], node[v], k)); putchar('\n');            }        }        puts("");    }    return 0;}/*1 61 2 12 4 12 5 21 3 13 6 2DIST 4 6KTH 4 6 4KTH 6 5 4DIST 2 5*/
0 0
原创粉丝点击