zoukankan      html  css  js  c++  java
  • SPOJ QTREE2 lct

    题目链接
    题意:
    给一棵树。有边权
    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 
    ", 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(' '); for (x = null; y != null; x = y, y = y->fa){ y->splay(); // for (int i = 1; i <= n; i++)debug(node[i]), putchar(' '); 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(' '); else { rd(k); pt(query_kth(node[u], node[v], k)); putchar(' '); } } puts(""); } return 0; } /* 1 6 1 2 1 2 4 1 2 5 2 1 3 1 3 6 2 DIST 4 6 KTH 4 6 4 KTH 6 5 4 DIST 2 5 */

  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7142139.html
Copyright © 2011-2022 走看看