zoukankan      html  css  js  c++  java
  • 洛谷 P1501 [国家集训队]Tree II

    洛谷 P1501 [国家集训队]Tree II        <<————————————————点击跳转

    这题就是一道LCT模板题

    需要注意一个小细节

    一看51061挺小的(呵呵)

    其实510612=2607225721>2147483647

    需要unsigned int

    不多说了   上代码:

    #include<cstdio>
    #define Rint register int
    using namespace std;
    typedef long long LL;
    const int N = 100003, mod = 51061;
    int sta[N], top;
    namespace LCT {
        void swap(int &a, int &b){a ^= b ^= a ^= b;}
        struct Node {
            int v, fa, siz, ch[2], sum, add, mul;
            bool rev;
        } e[N];
        void pushup(int x){
            e[x].sum = (e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].v) % mod;
            e[x].siz = e[e[x].ch[0]].siz + e[e[x].ch[1]].siz + 1;
        }
        void pushrev(int x){
            e[x].rev ^= 1;
            swap(e[x].ch[0], e[x].ch[1]);
        }
        void pushtag(int x, int add, int mul){
            if(!x) return;
            e[x].sum = ((LL) e[x].sum * mul + (LL) add * e[x].siz) % mod;
            e[x].add = ((LL) e[x].add * mul + add) % mod;
            e[x].v = ((LL) e[x].v * mul + add) % mod;
            e[x].mul = (LL) e[x].mul * mul % mod;
        }
        void pushdown(int x){
            if(e[x].rev){
                e[x].rev = false;
                if(e[x].ch[0]) pushrev(e[x].ch[0]);
                if(e[x].ch[1]) pushrev(e[x].ch[1]);
            }
            pushtag(e[x].ch[0], e[x].add, e[x].mul);
            pushtag(e[x].ch[1], e[x].add, e[x].mul);
            e[x].add = 0; e[x].mul = 1;
        }
        bool nroot(int x){
            return e[e[x].fa].ch[0] == x || e[e[x].fa].ch[1] == x;
        }
        void rotate(int x){
            int y = e[x].fa, z = e[y].fa, zson = e[z].ch[1] == y, yson = e[y].ch[1] == x, B = e[x].ch[yson ^ 1];
            if(nroot(y)) e[z].ch[zson] = x;
            e[x].ch[yson ^ 1] = y;
            e[y].ch[yson] = B;
            if(B) e[B].fa = y;
            e[y].fa = x;
            e[x].fa = z;
            pushup(y);
        }
        void splay(int x){
            int now = x;
            sta[++ top] = x;
            while(nroot(now)) sta[++ top] = now = e[now].fa;
            while(top) pushdown(sta[top --]);
            while(nroot(x)){
                int y = e[x].fa, z = e[y].fa;
                if(nroot(y))
                    rotate((e[z].ch[1] == y) ^ (e[y].ch[1] == x) ? x : y);
                rotate(x);
            }
            pushup(x);
        }
        void access(int x){
            for(Rint y = 0;x;y = x, x = e[x].fa){
                splay(x); e[x].ch[1] = y; pushup(x);
            }
        }
        void makeroot(int x){
            access(x); splay(x); pushrev(x);
        }
        int findroot(int x){
            access(x); splay(x);
            while(e[x].ch[0]) {pushdown(x); x = e[x].ch[0];}
            return x;
        }
        void split(int x, int y){
            makeroot(x); access(y); splay(y);
        }
        void link(int x, int y){
            makeroot(x);
            e[x].fa = y;
        }
        void cut(int x, int y){
            makeroot(x);
            if(findroot(y) == x && e[x].fa == y && !e[x].ch[1]){
                e[x].fa = e[y].ch[0] = 0;
                pushup(y);
            }
        }
    }
    using namespace LCT;
    int n, q;
    int main(){
        scanf("%d%d", &n, &q);
        for(Rint i = 1;i <= n;i ++)
            e[i].v = e[i].sum = e[i].mul = 1;
        for(Rint i = 1;i < n;i ++){
            int a, b;
            scanf("%d%d", &a, &b);
            link(a, b);
        }
        while(q --){
            char opt[5];
            scanf("%s", opt);
            int a, b, c, d;
            switch(opt[0]){
                case '+':
                    scanf("%d%d%d", &a, &b, &c);
                    split(a, b);
                    pushtag(b, c, 1);
                    break;
                case '-':
                    scanf("%d%d%d%d", &a, &b, &c, &d);
                    cut(a, b); link(c, d);
                    break;
                case '*':
                    scanf("%d%d%d", &a, &b, &c);
                    split(a, b);
                    pushtag(b, 0, c);
                    break;
                case '/':
                    scanf("%d%d", &a, &b);
                    split(a, b);
                    printf("%d\n", e[b].sum);
            }
        }
    }
  • 相关阅读:
    ubuntu安装mysql并使用Navicat连接
    二叉树基础知识点
    Javascript 16进制转有符号的10进制整数
    Node.js 学习笔记(二)
    API测试如何演变为应用程序开发的常规部分
    API在线文档
    API文档自动生成的方法
    快速对比API版本
    如何使用OPENAPI进行质量检查
    【分享】什么是API网关?大公司为什么都有API网关?
  • 原文地址:https://www.cnblogs.com/weilinxiao/p/10985554.html
Copyright © 2011-2022 走看看