您的位置:首页 > 其它

bzoj 2631(link cut tree)

2016-05-29 18:50 330 查看

2631: tree

Time Limit: 30 Sec Memory Limit: 128 MB

Submit: 3372 Solved: 1135

[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

解题思路:link cut tree模板,市赛打击后的第一题,加油吧。



#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

using namespace std;

int n,qg,len;

const int maxn=51061;

int to[300000],next[300000],h[300000];

unsigned int fa[110000],l[110000],r[110000],rever[110000],size[110000];

unsigned int zhi[110000],sum[110000],add[110000],mul[110000];

int q[110000];

inline int read()

{

char y; int x=0,f=1; y=getchar();

while (y<'0'||y>'9') {if (y=='-') f=-1; y=getchar();}

while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}

return x*f;

}

void insert(int x,int y)

{

++len; to[len]=y; next[len]=h[x]; h[x]=len;

}

void dfs(int now,int f)

{

fa[now]=f; l[now]=r[now]=add[now]=rever[now]=0; sum[now]=zhi[now]=mul[now]=1; size[now]=1;

int u=h[now];

while (u!=0)

{

if (to[u]!=f)

{

dfs(to[u],now);

}

u=next[u];

}

}

void pushdown(int now)

{

if (rever[now])

{

rever[l[now]]^=1; rever[r[now]]^=1;

rever[now]^=1; swap(l[now],r[now]);

}

if (mul[now]!=1)

{

if (l[now])mul[l[now]]=mul[l[now]]*mul[now]%maxn,zhi[l[now]]=zhi[l[now]]*mul[now]%maxn,sum[l[now]]=sum[l[now]]*mul[now]%maxn,add[l[now]]=add[l[now]]*mul[now]%maxn;

if (r[now])mul[r[now]]=mul[r[now]]*mul[now]%maxn,zhi[r[now]]=zhi[r[now]]*mul[now]%maxn,sum[r[now]]=sum[r[now]]*mul[now]%maxn,add[r[now]]=add[r[now]]*mul[now]%maxn;

mul[now]=1;

}

if (add[now]!=0)

{

if (l[now])add[l[now]]=(add[l[now]]+add[now])%maxn,zhi[l[now]]=(zhi[l[now]]+add[now])%maxn,sum[l[now]]=(sum[l[now]]+add[now]*size[l[now]]%maxn)%maxn;

if (r[now])add[r[now]]=(add[r[now]]+add[now])%maxn,zhi[r[now]]=(zhi[r[now]]+add[now])%maxn,sum[r[now]]=(sum[r[now]]+add[now]*size[r[now]]%maxn)%maxn;

add[now]=0;

}

}

void maindown(int now)

{

sum[now]=(sum[l[now]]+sum[r[now]]+zhi[now])%maxn;

size[now]=size[l[now]]+size[r[now]]+1;

}

bool isroot(int now)

{

if (l[fa[now]]==now || r[fa[now]]==now) return false;else return true;

}

void rotate(int x)

{

int y=fa[x]; int z=fa[y];

if (!isroot(y))

{

if (l[z]==y) l[z]=x; else r[z]=x;

}

fa[x]=z; fa[y]=x;

if (l[y]==x)

{

fa[r[x]]=y; l[y]=r[x]; r[x]=y;

}else

{

fa[l[x]]=y; r[y]=l[x]; l[x]=y;

}

maindown(y); maindown(x);

}

void splay(int x)

{

int now=x; int tail=1; q[tail]=x;

while (!isroot(now)) {++tail; q[tail]=fa[now]; now=fa[now];}

for (int i=tail;i>=1;--i) pushdown(q[i]);

while (!isroot(x))

{

int y=fa[x]; int z=fa[y];

if (!isroot(y))

{

if (l[z]==y ^ l[y]==x) rotate(x);else rotate(y);

}

rotate(x);

}

}

void access(int now)

{

splay(now);

while (fa[now]!=0)

{

splay(fa[now]); r[fa[now]]=now;

r[now]=0; maindown(now);

maindown(fa[now]);

splay(now);

}

splay(now); r[now]=0; maindown(now);

}

void makeroot(int now)

{

access(now); splay(now); rever[now]^=1;

}

int main()

{

n=read(); qg=read();

for (int i=1;i<=n-1;++i)

{

int u,v; u=read(); v=read();

insert(u,v); insert(v,u);

}

dfs(1,0);

for (int y=1;y<=qg;++y)

{

char c[10];

scanf("%s",c);

if (c[0]=='*')

{

int u,v,c; u=read(); v=read(); c=read();

c=c%maxn;

makeroot(u); access(v); splay(u); zhi[u]=zhi[u]*c%maxn; sum[u]=sum[u]*c%maxn; mul[u]=mul[u]*c%maxn; add[u]=add[u]*c%maxn;

}else

if (c[0]=='-')

{

int u1,v1,u2,v2;

u1=read(); v1=read(); u2=read(); v2=read();

makeroot(u1); access(v1); splay(u1); r[u1]=0; fa[v1]=0; maindown(u1);

access(u2); makeroot(v2); splay(u2); fa[v2]=u2;

}else

if (c[0]=='/')

{

int u,v; u=read(); v=read();

makeroot(u);

access(v);

splay(u); printf("%d\n",sum[u]%maxn);

}else

if (c[0]=='+')

{

int u,v,c; u=read(); v=read(); c=read();

c=c%maxn;

makeroot(u);

access(v); splay(u);

zhi[u]=(zhi[u]+c)%maxn; sum[u]=(sum[u]+size[u]*c%maxn)%maxn; add[u]=(add[u]+c)%maxn;

}

}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: