• [国家集训队]Tree II


    LCT板子题。

    和线段树2的操作方法一样,先乘后加就行了。洛谷评分虚高

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=100005,mod=51061;
    int n,q,ch[N][2],fa[N];long long val[N];long long siz[N];
    long long sum[N],add[N],mul[N];
    bool rev[N];
    bool is_rt(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];}
    bool ck(int x) {return x==ch[fa[x]][1];}
    void pushup(int x) {
        siz[x]=siz[ch[x][1]]+siz[ch[x][0]]+1;
        sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
    }
    void pushdown(int x) {
        if(mul[x]!=1) {
            if(ch[x][1])
                (sum[ch[x][1]]*=mul[x])%=mod,
                (val[ch[x][1]]*=mul[x])%=mod,
                (add[ch[x][1]]*=mul[x])%=mod,
                (mul[ch[x][1]]*=mul[x])%=mod;
            if(ch[x][0])
                (sum[ch[x][0]]*=mul[x])%=mod,
                (val[ch[x][0]]*=mul[x])%=mod,
                (add[ch[x][0]]*=mul[x])%=mod,
                (mul[ch[x][0]]*=mul[x])%=mod;
            mul[x]=1;
        }
        if(add[x]) {
            if(ch[x][0])
                (sum[ch[x][0]]+=add[x]*siz[ch[x][0]])%=mod,
                (val[ch[x][0]]+=add[x])%=mod,
                (add[ch[x][0]]+=add[x])%=mod;
            if(ch[x][1])
                (sum[ch[x][1]]+=add[x]*siz[ch[x][1]])%=mod,
                (val[ch[x][1]]+=add[x])%=mod,
                (add[ch[x][1]]+=add[x])%=mod;
            add[x]=0;
        }
        if(rev[x]) {
            swap(ch[x][0],ch[x][1]);
            rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
            rev[x]=0;
        }
    }
    
    void rotate(int x) {
        int f=fa[x],ff=fa[f];
        if(!is_rt(f)) ch[ff][ck(f)]=x;
        bool tag=ck(x);
        ch[f][tag]=ch[x][tag^1];
        fa[ch[f][tag]]=f;
        ch[x][tag^1]=f;
        fa[f]=x;
        fa[x]=ff;
        pushup(f);pushup(x);
    }
    int stk[N],top;
    void splay(int x) {
        stk[top=1]=x;
        for(int i=x;!is_rt(i);i=fa[i]) stk[++top]=fa[i];
        for(int i=top;i;i--) pushdown(stk[i]);
        for(int f;!is_rt(x);rotate(x)) {
            if(!is_rt(f=fa[x])) rotate(ck(f)==ck(x)?f:x);
        }
    }
    void access(int x) {
        for(int t=0;x;t=x,x=fa[x]) {
            splay(x);ch[x][1]=t;pushup(x);
        }
    }
    void makeroot(int x) {
        access(x);
        splay(x);
        rev[x]^=1;
    }
    void link(int x,int y) {
        makeroot(x);
        fa[x]=y;
    }
    void cut(int x,int y) {
        makeroot(x);access(y);splay(y);
        ch[y][0]=fa[x]=0;
    }
    int main() {
        scanf("%d%d",&n,&q);
        for(int i=1;i<N;i++) mul[i]=1,val[i]=1,siz[i]=1;
        for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),link(u,v);
        char opt[10];int a,b,c,d;
        while(q--) {
            scanf("%s",opt);
            switch(opt[0]) {
                case '+':scanf("%d%d%d",&a,&b,&c);
                         makeroot(a);access(b);splay(b);
                         (add[b]+=c)%=mod;(val[b]+=c)%=mod;(sum[b]+=c*siz[b])%=mod;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);
                         makeroot(a),access(b);splay(b);
                         (mul[b]*=c)%=mod;(val[b]*=c)%=mod;(sum[b]*=c)%=mod;(add[b]*=c)%=mod;break;
                case '/':scanf("%d%d",&a,&b);
                         makeroot(a),access(b);splay(b);
                         printf("%lld
    ",sum[b]);break;
            }
        }
    }
    Tree II
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    Activity跳转动画
    如何查询自己的手机版本?欧版、亚太、港行、还是国行?
    VC程序员常用工具汇总
    陈灯可重用代码段管理器VS插件版5.0发布(代码段收集器、个人代码库、代码片段管理、代码管理)
    基于OSLC的系统集成
    安桌点菜源代码
    eclipse jsp 文字设置
    ubuntu 下 netbeans平台 使用C连接mysql
    使用gdi+实时绘制picturebox(画个叉)
    思路上的转变,运用投影和一阶导数的思想
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9732692.html
Copyright © 2020-2023  润新知