zoukankan      html  css  js  c++  java
  • bzoj2631: tree

    搬运。要开LL,注意两个遗传标记之间影响。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int mod=51061;
    struct node
    {
        int f,c,son[2];
        LL d,s,ad,ch;
        bool fz;
    }tr[310000];
    void add(int x)
    {
        if(x==0)return ;
        tr[x].s=(tr[x].s+tr[x].ad*tr[x].c)%mod;
        tr[x].d=(tr[x].d+tr[x].ad)%mod;
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[lc].ad=(tr[lc].ad+tr[x].ad)%mod;
        tr[rc].ad=(tr[rc].ad+tr[x].ad)%mod;
        tr[x].ad=0;
    }
    void mul(int x)
    {
        if(x==0)return ;
        tr[x].s=(tr[x].s*tr[x].ch)%mod;
        tr[x].d=(tr[x].d*tr[x].ch)%mod;
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[lc].ch=(tr[lc].ch*tr[x].ch)%mod;
        tr[lc].ad=(tr[lc].ad*tr[x].ch)%mod;
        tr[rc].ch=(tr[rc].ch*tr[x].ch)%mod;
        tr[rc].ad=(tr[rc].ad*tr[x].ch)%mod;
        tr[x].ch=1;
    }
    void update(int x)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[x].c=tr[lc].c+tr[rc].c+1;
        if(tr[lc].ch!=1)mul(lc);
        if(tr[rc].ch!=1)mul(rc);
        if(tr[lc].ad!=0)add(lc);
        if(tr[rc].ad!=0)add(rc);
        tr[x].s=(tr[lc].s+tr[rc].s+tr[x].d)%mod;
    }
    void reverse(int x)
    {
        tr[x].fz=false;
        swap(tr[x].son[0],tr[x].son[1]);
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[lc].fz=1-tr[lc].fz;
        tr[rc].fz=1-tr[rc].fz;
    }
    void rotate(int x,int w)
    {
        int f=tr[x].f,ff=tr[f].f;
        int R,r;
         
        R=f;r=tr[x].son[w];
        tr[R].son[1-w]=r;
        if(r!=0)tr[r].f=R;
         
        R=ff;r=x;
             if(tr[R].son[0]==f)tr[R].son[0]=r;
        else if(tr[R].son[1]==f)tr[R].son[1]=r;
        tr[r].f=R;
         
        R=x;r=f;
        tr[R].son[w]=r;
        tr[r].f=R;
         
        update(f);
        update(x);
    }
    int tmp[310000];
    void splay(int x,int rt)
    {
        int s=0,i=x;
        while(tr[i].f!=rt&&(tr[tr[i].f].son[0]==i||tr[tr[i].f].son[1]==i))
        {
            tmp[++s]=i;
            i=tr[i].f;
        } 
        tmp[++s]=i;
        while(s!=0)
        {
            i=tmp[s];s--;
            if(tr[i].fz==true)reverse(i);
            if(tr[i].ch!=1)mul(i);
            if(tr[i].ad!=0)add(i);
        }
         
        while(tr[x].f!=rt&&(tr[tr[x].f].son[0]==x||tr[tr[x].f].son[1]==x))
        {
            int f=tr[x].f,ff=tr[f].f;
            if(ff==rt||(tr[ff].son[0]!=f&&tr[ff].son[1]!=f))
            {
                if(x==tr[f].son[0])rotate(x,1);
                else               rotate(x,0);
            }
            else
            {
                     if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);}
                else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);}
                else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);}
                else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);}
            }
        }
    }
    int n;
    void make_tree()
    {
        tr[0].f=0;tr[0].c=0;
        tr[0].d=0;tr[0].s=0;
        tr[0].son[0]=tr[0].son[1]=0;
        tr[0].ad=0;tr[0].ch=1;
        tr[0].fz=false;
        for(int i=1;i<=n;i++)
        {
            tr[i].f=0;tr[i].c=1;
            tr[i].d=1;tr[i].s=1;
            tr[i].son[0]=tr[i].son[1]=0;
            tr[i].ad=0;tr[i].ch=1;
            tr[i].fz=false;
        }
    }
    void access(int x) 
    {
        int y=0;
        while(x!=0)
        {
            splay(x,0);
            tr[x].son[1]=y;
            if(y!=0)tr[y].f=x;
            y=x;x=tr[x].f;
        }
    }
    void makeroot(int x)
    {
        access(x);splay(x,0);
        tr[x].fz=1-tr[x].fz;
    }
    void link(int x,int y)
    {
        makeroot(x);tr[x].f=y;access(x);
    }
    void cut(int x,int y)
    {
        makeroot(x);
        access(y);splay(y,0);
        tr[tr[y].son[0]].f=0;tr[y].son[0]=0;
        update(y);
    }
    int find_root(int x)
    {
        access(x);splay(x,0);
        while(tr[x].son[0]!=0)x=tr[x].son[0];
        return x;
    }
    void increase(int x,int y,LL W)
    {
        makeroot(x);
        access(y);splay(y,0);
        tr[y].ad=(tr[y].ad+W)%mod;
    }
    void multiply(int x,int y,LL W)
    {
        makeroot(x);
        access(y);splay(y,0);
        tr[y].ch=(tr[y].ch*W)%mod;
    }
    LL getsum(int x,int y)
    {
        makeroot(x);
        access(y);splay(y,0);
        update(y);return tr[y].s%mod;
    }
    struct edge
    {
        int x,y;
    }e[310000];
    char ss[10];
    int main()
    {
    //  freopen("tree.in","r",stdin);
    //  freopen("tree.out","w",stdout);
        int m,x,y;
        LL W;
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)scanf("%d%d",&e[i].x,&e[i].y);
        make_tree();
        for(int i=1;i<n;i++)link(e[i].x,e[i].y);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",ss+1);
            if(ss[1]=='+')
            {
                scanf("%d%d%lld",&x,&y,&W);
                increase(x,y,W);
            }
            else if(ss[1]=='*')
            {
                scanf("%d%d%lld",&x,&y,&W);
                multiply(x,y,W);
            }
            else if(ss[1]=='-')
            {
                scanf("%d%d",&x,&y);cut(x,y);
                scanf("%d%d",&x,&y);link(x,y);
            }
            else
            {
                scanf("%d%d",&x,&y);
                printf("%lld
    ",getsum(x,y));
            }
        }
        return 0;
    }
  • 相关阅读:
    PHP页面静态化
    PHP实现单文件、多文件上传 封装 面向对象实现文件上传
    PHP MYSQL
    MySQL 数据表
    MySQL基础
    DOM事件处理程序-事件对象-键盘事件
    JS--显示类型转换Number—隐式类型转换
    JS的数据类型
    JS属性读写操作+if判断注意事项
    Javascript进阶篇——总结--DOM案例+选项卡效果
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8135284.html
Copyright © 2011-2022 走看看