zoukankan      html  css  js  c++  java
  • HDU 4010.Query on The Trees 解题报告

    题意:

      给出一颗树,有4种操作:

         1、如果x和y不在同一棵树上则在xy连边

         2、如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离

         3、如果x和y在同一棵树上则x到y的路径上所有的点权值+w

         4、如果x和y在同一棵树上则输出x到y路径上的最大值

    动态树入门题:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    const int MAXN = 333333;
    
    struct node {
        int val, max, inc;
        bool rev;
        node *par, *Ch[2];
    } dt[MAXN], *NIL = dt;
    
    struct LinkcutTree {
        inline void _inc (node * x,  int inc) {
            if (x == NIL) return;
            x->inc += inc, x->val += inc, x->max += inc;
        }
        inline void clear (node *const x) {
            if (x == NIL) return ;
            if (x->inc) {
                _inc (x->Ch[0], x->inc);
                _inc (x->Ch[1], x->inc);
                x->inc = 0;
            }
            if (x->rev) {
                swap (x->Ch[0], x->Ch[1]);
                x->Ch[0]->rev ^= 1;
                x->Ch[1]->rev ^= 1;
                x->rev = 0;
            }
        }
        inline void update (node * x) {
            clear (x);
            clear (x->Ch[0]), clear (x->Ch[1]);
            x->max = max (x->val, max (x->Ch[0]->max, x->Ch[1]->max) );
        }
        void Rotate (node *x) {
            node *p = x->par, *g = p->par;
            clear (p),clear (x);
            int c = p->Ch[0] == x; //0左旋,1右旋
            p->Ch[c ^ 1] = x->Ch[c];
            if (x->Ch[c] != NIL) x->Ch[c]->par = p;
            x->par = g;
            if (g->Ch[0] == p) g->Ch[0] = x; else
                  if (g->Ch[1] == p) g->Ch[1] = x;
            x->Ch[c] = p;
            p->par = x;
            update (p);
        }
        void Splay (node *x) {
               if(x==NIL) return ;
            while (x->par != NIL && (x->par->Ch[0] == x || x->par->Ch[1] == x) ) {
                if (x->par != NIL)
                    Rotate (x);
                else {
                    node *p = x->par, *g = p->par;
                    if ( (g->Ch[1] == p) == (p->Ch[1] == x) )
                        Rotate (p), Rotate (x);
                    else
                        Rotate (x), Rotate (x);
                }
            }
            update (x);
        }
        node *Access (node *u) {
            node *v = NIL;
            for (; u != NIL; u = u->par) {
                Splay (u);
                u->Ch[1] = v;
                update (v = u);
            }
            return v;
        }
        node *getroot (node *x) {
            for (x = Access (x); clear (x), x->Ch[0] != NIL; x = x->Ch[0]);
            return x;
        }
        inline void evert (node *x) {
            Access (x)->rev ^= 1;
            Splay (x);
        }
        inline void link (node *x, node *y) {
            evert (x);
            x->par = y;
            Access (x);
        }
        inline void cut (node *x, node *y) {
            evert (x);
            Access (y);
            Splay (y);
            y->Ch[0]->par = NIL;
            y->Ch[0] = NIL;
            update (y);
        }
        inline int query (node *x, node *y) {
            evert (x);
            Access (y), Splay (y);
            return y->max;
        }
        inline void modify (node *x, node *y, int w) {
            evert (x);
            Access (y), Splay (y);
            _inc (y, w);
        }
    } LCT;
    int n, m;
    int main() {
        while (scanf ("%d", &n) != EOF) {
            for (int i = 0; i <= n; i++) {
                dt[i].val = dt[i].max = dt[i].inc = 0;
                dt[i].par = dt[i].Ch[0] = dt[i].Ch[1] = NIL;
                dt[i].rev = 0;
            }
            for (int i = 1, x, y; i < n; ++i) {
                scanf ("%d %d", &x, &y);
                LCT.link (dt + x, dt + y);
            }
            for (int i = 1, x; i <= n; ++i) {
                scanf ("%d", &x);
                node *tem = dt + i;
                LCT.Splay (tem);
                tem->val = tem->max = x;
                LCT.update (tem);
            }
            scanf ("%d", &m);
            for (int i = 0, op, x, y, z; i < m; ++i) {
                scanf ("%d%d%d", &op, &x, &y);
                switch (op) {
                case 1:
                    if (LCT.getroot (dt + x) == LCT.getroot (dt + y) ) printf ("-1
    ");
                    else LCT.link (dt + x, dt + y); break;
                case 2:
                    if (x == y || LCT.getroot (dt + x) != LCT.getroot (dt + y) ) printf ("-1
    ");
                    else LCT.cut (dt + x, dt + y); break;
                case 3:
                    scanf ("%d", &z);
                    if (LCT.getroot (dt + y) != LCT.getroot (dt + z) ) printf ("-1
    ");
                    else LCT.modify (dt + y, dt + z, x); break;
                case 4:
                    if (LCT.getroot (dt + x) != LCT.getroot (dt + y) ) printf ("-1
    ");
                    else printf ("%d
    ", LCT.query (dt + x, dt + y) ); break;
                }
            }
            putchar (10);
        }
    }
    View Code
  • 相关阅读:
    URL记录
    Mongodb集群节点故障恢复场景分析(转)
    IO 和 NIO 的区别
    VUE 前端项目优化方法
    缓存的穿透和雪崩
    接口如何处理重复请求?
    线程池构造类 ThreadPoolExecutor 的 5 个参数
    大型网站在架构上应当考虑哪些问题
    synchronized 和 lock 的区别
    JVM虚拟机 YGC和FGC发生的具体场景
  • 原文地址:https://www.cnblogs.com/keam37/p/4006257.html
Copyright © 2011-2022 走看看