2631: tree
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 4855 Solved: 1659
[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行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
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
LCT练手题
pushdown写错调一上午。
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef unsigned int uint;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=100100,mod=51061;
int ch[N][2],size[N],fa[N];
uint V[N],sum[N],add[N],mul[N];
bool rev[N];
inline void pushup(int k)
{
int ls=ch[k][0],rs=ch[k][1];
size[k]=size[ls]+size[rs]+1;
sum[k]=(sum[ls]+sum[rs]+V[k])%mod;
}
inline void pushdown(int k)
{
int ls=ch[k][0],rs=ch[k][1];
if(mul[k]!=1)
{
(V[ls]*=mul[k])%=mod;
(V[rs]*=mul[k])%=mod;
(mul[ls]*=mul[k])%=mod;
(mul[rs]*=mul[k])%=mod;
(add[ls]*=mul[k])%=mod;
(add[rs]*=mul[k])%=mod;
(sum[ls]*=mul[k])%=mod;
(sum[rs]*=mul[k])%=mod;
mul[k]=1;
}
if(add[k])
{
sum[ls]=(sum[ls]+add[k]*size[ls])%mod;
sum[rs]=(sum[rs]+add[k]*size[rs])%mod;
(add[ls]+=add[k])%=mod;
(add[rs]+=add[k])%=mod;
(V[ls]+=add[k])%=mod;
(V[rs]+=add[k])%=mod;
add[k]=0;
}
if(rev[k])
{
rev[k]=0;
rev[ls]^=1;rev[rs]^=1;
swap(ch[k][0],ch[k][1]);
}
}
inline bool isroot(int k)
{return ch[fa[k]][0]!=k&&ch[fa[k]][1]!=k;}
void getdown(int k)
{
if(!isroot(k)) getdown(fa[k]);
pushdown(k);
}
inline void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
l=(ch[y][1]==x);r=l^1;
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x)
{
getdown(x);
int y,z;
while(!isroot(x))
{
y=fa[x];z=fa[y];
if(!isroot(y))
{
if((ch[y][0]==x)^(ch[z][0]==y))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{int t=0;while(x){splay(x);ch[x][1]=t;pushup(x);t=x;x=fa[x];}}
void rever(int x)
{access(x);splay(x);rev[x]^=1;}
void split(int u,int v)
{rever(u);access(v);splay(v);}
void link(int u,int v)
{rever(u);fa[u]=v;splay(u);}
void cut(int u,int v)
{split(u,v);ch[v][0]=fa[u]=0;}
void modify_add(int u,int v,int val)
{
split(v,u);
sum[u]=(sum[u]+size[u]*val)%mod;
(add[u]+=val)%=mod;
(V[u]+=val)%=mod;
}
void modify_mul(int u,int v,int val)
{
split(v,u);
(sum[u]*=val)%=mod;
(mul[u]*=val)%=mod;
(add[u]*=val)%=mod;
(V[u]*=val)%=mod;
}
void query(int u,int v)
{
split(v,u);
print(sum[u]);puts("");
}
int main()
{
register int n=read(),Q=read();
register int u,v,x,y;
for(u=1;u<=n;++u)
mul[u]=V[u]=sum[u]=size[u]=1;
for(x=1;x<n;++x)
{
u=read();v=read();
link(u,v);
}
char opt[2];
while(Q--)
{
scanf("%s",opt);
u=read();v=read();
switch(opt[0])
{
case '+':
x=read();
modify_add(u,v,x);
break;
case '-':
x=read();y=read();
cut(u,v);link(x,y);
break;
case '*':
x=read();
modify_mul(u,v,x);
break;
case '/':
query(u,v);
break;
}
}
return 0;
}