人生有信仰 数据有梯度 暴力不爆零


bzoj 2631: tree -- LCT

2631: tree

Time Limit: 30 Sec  Memory Limit: 128 MB

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


 

 

Source

LCT入门题,,

md一个%=写成了%改了我一天。。。

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000007
#define ll long long
#define uint unsigned int
#define mod 51061
#define N 100010
inline int rd()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int c[N][2],fa[N],sz[N];
uint lz1[N],lz2[N],v[N],sum[N];
bool rev[N];
int n,q;
#define ls c[x][0]
#define rs c[x][1]
bool isrt(int x){return x!=c[fa[x]][0]&&x!=c[fa[x]][1];}
inline void pd(int x)
{
    uint mz;
    if(rev[x])
    {
        rev[ls]^=1;rev[rs]^=1;
        swap(ls,rs);rev[x]=0;
    }
    mz=lz2[x];lz2[x]=1;
    if(mz!=1)
    {
        lz2[ls]=lz2[ls]*mz%mod;
        lz2[rs]=lz2[rs]*mz%mod;
        lz1[ls]=lz1[ls]*mz%mod;
        lz1[rs]=lz1[rs]*mz%mod;
        sum[ls]=sum[ls]*mz%mod;
        sum[rs]=sum[rs]*mz%mod;
        v[ls]=v[ls]*mz%mod;v[rs]=v[rs]*mz%mod;
    }
    mz=lz1[x];lz1[x]=0;
    if(mz)
    {
        (lz1[ls]+=mz)%=mod;
        (lz1[rs]+=mz)%=mod;
        (sum[ls]+=sz[ls]*mz)%=mod;
        (sum[rs]+=sz[rs]*mz)%=mod;
        (v[ls]+=mz)%=mod;(v[rs]+=mz)%=mod;
    }
}
inline void upd(int x)
{
    sz[x]=sz[ls]+sz[rs]+1;
    sum[x]=(v[x]+sum[ls]+sum[rs])%mod;
}
void rot(int x)
{
    int y=fa[x],z=fa[y],l,r;
    l=c[y][1]==x;r=l^1;
    if(!isrt(y)) c[z][c[z][1]==y]=x;
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    upd(y);upd(x);
}

int st[N],tot;
void splay(int x)
{
    tot=1;st[1]=x;
    for(int i=x;!isrt(i);i=fa[i]) st[++tot]=fa[i];
    for(int i=tot;i;i--) pd(st[i]);
    int y,z;
    while(!isrt(x))
    {
        y=fa[x];z=fa[y];
        if(!isrt(y))
        {
            if((c[y][0]==x)^(c[z][0]==y)) rot(x);
            else rot(y);
        }
        rot(x);
    }
}
void acc(int x)
{
    int t=0;
    while(x)
    {
        splay(x);
        rs=t;upd(x);
        t=x;x=fa[x];
    }
}
void rever(int x)
{
    acc(x);
    splay(x);
    rev[x]^=1;
}
void mk(int x,int y)
{
    rever(x);
    acc(y);splay(y);
}
void link(int x,int y)
{
    rever(x);
    fa[x]=y;
}
void cut(int x,int y)
{
    mk(x,y);
    c[y][0]=fa[x]=0;
}
inline void mul(int x,int V)
{
    (v[x]*=V)%=mod;
    (sum[x]*=V)%=mod;
    (lz2[x]*=V)%=mod;
    (lz1[x]*=V)%=mod;
}
inline void add(int x,int V)
{
    (v[x]+=V)%=mod;
    (sum[x]+=V*sz[x])%=mod;
    (lz1[x]+=V)%=mod;
}
int main()
{
    n=rd();q=rd();
    for(int i=1;i<=n;i++) lz2[i]=sz[i]=sum[i]=v[i]=1;
    for(int i=1,x,y;i<n;i++)
    {
        x=rd();y=rd();
        link(x,y);
    }
    char op[2];
    int x,y,xx,yy,V;
    while(q--)
    {
        scanf("%s",op);
        if(op[0]=='*')
        {
            x=rd();y=rd();V=rd();
            mk(x,y);mul(y,V);
        }
        else if(op[0]=='+')
        {
            x=rd();y=rd();V=rd();
            mk(x,y);add(y,V);
        }
        else if(op[0]=='-')
        {
            x=rd();y=rd();xx=rd();yy=rd();
            cut(x,y);link(xx,yy);
        }
        else 
        {
            x=rd();y=rd();
            mk(x,y);printf("%d\n",sum[y]);
        }
    }
    return 0;
}

 

posted @ 2017-12-20 19:15 lkhll 阅读(...) 评论(...) 编辑 收藏