zoukankan      html  css  js  c++  java
  • BZOJ 2631: tree [LCT splay区间]

    2631: tree

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 3854  Solved: 1292
    [Submit][Status][Discuss]

    Description

     一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
    + u v c:将u到v的路径上的点的权值都加上自然数c;
    - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
    * u v c:将u到v的路径上的点的权值都乘上自然数c;
    / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

    Input

      第一行两个整数n,q
    接下来n-1行每行两个正整数u,v,描述这棵树
    接下来q行,每行描述一个操作

    Output

      对于每个/对应的答案输出一行

    Sample Input

    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1

    Sample Output

    4

    HINT

    数据规模和约定

    10%的数据保证,1<=n,q<=2000

    另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

    另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

    100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


    煞笔错误,毁我青春

    把i打成x

    标记和维护序列一样,只不过这次用splay而已 http://www.cnblogs.com/candy99/p/5951198.html

    提取链直接写了个split,和splay的区间操作很像哈

    然后usigned int即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=1e5+5,MOD=51061;
    typedef unsigned int ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct node{
        int ch[2],fa,rev,size;
        ll sum,w,add,mul;
        node():add(0),mul(1){}
    }t[N];
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    
    inline void update(int x){
        t[x].sum=(t[lc].sum+t[rc].sum+t[x].w)%MOD;
        t[x].size=(t[lc].size+t[rc].size+1)%MOD;
    }
    inline void paint(int x,ll d,ll v){//printf("paint %d %d %d
    ",x,d,v);
        t[x].add=(t[x].add*v+d)%MOD;
        t[x].mul=(t[x].mul*v)%MOD;
        t[x].w=(t[x].w*v+d)%MOD;
        t[x].sum=(t[x].sum*v+d*t[x].size)%MOD;//printf("sum %d
    ",t[x].sum);
    }
    inline void pushDown(int x){
        if(t[x].rev){
            t[lc].rev^=1;
            t[rc].rev^=1;
            swap(lc,rc);
            t[x].rev=0;
        }
        if(t[x].add||t[x].mul!=1){
            paint(lc,t[x].add,t[x].mul);
            paint(rc,t[x].add,t[x].mul);
            t[x].add=0;
            t[x].mul=1;
        }
    }
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
            update(x);
        }
    }
    inline void MakeRoot(int x){
        Access(x);splay(x);
        t[x].rev^=1;
    }
    inline int FindRoot(int x){
        Access(x);splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeRoot(x);
        t[x].fa=y;    
    }
    inline void Cut(int x,int y){
        MakeRoot(x);
        Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
    }
    inline void split(int x,int y){
        MakeRoot(x);Access(y);splay(y);
    }
    int n,Q,op,x,y,c;
    char s[3];
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();Q=read();
        for(int i=1;i<=n-1;i++) 
            x=read(),y=read(),Link(x,y),t[i].size=t[i].w=t[i].sum=1;
        t[n].size=t[n].w=t[n].sum=1;
        while(Q--){
            scanf("%s",s); x=read();y=read();
            if(s[0]=='+') c=read(),split(x,y),paint(y,c,1);
            if(s[0]=='-'){
                Cut(x,y);
                x=read();y=read();
                Link(x,y);
            }
            if(s[0]=='*') c=read(),split(x,y),paint(y,0,c);
            if(s[0]=='/') split(x,y),printf("%d
    ",t[y].sum);
        }
    }
  • 相关阅读:
    day24.魔术方法 __del__ __str__ __repr __call__ __bool__ __len__ \__add__
    Hibernate事务管理
    Hibernate持久化类和Hibernate持久化对象状态
    LeetCode-Largest Rectangle in Histogram
    LeetCode-Word Break
    LeetCode-Spiral Matrix
    LeetCode-Spiral Matrix II
    LeetCode-Binary Tree Zigzag Level Order Traversal
    LeetCode-Multiply Strings
    LeetCode-Copy List with Random Pointer
  • 原文地址:https://www.cnblogs.com/candy99/p/6274826.html
Copyright © 2011-2022 走看看