一棵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的余数。
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
对于每个/对应的答案输出一行
3 2
1 2
2 3
* 1 3 4
/ 1 1
4
数据规模和约定
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
同时又加和乘,维护标记和这个题很像:【bzoj1798】[Ahoi2009]Seq 维护序列seq
然后就是LCT的路径操作……
别忘了模,务必不要忘了模!!在maintain函数中务必不要忘了模!!(来自因此浪费了半个下午时间的我)
unsigned int!!不然会WA
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned int LL;
const int mod = 51061;
const int SZ = 1000010;
const int INF = 1000000010;
struct node{
node *f,*ch[2];
LL sz,v,sum;
LL add,c;
bool rev;
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
void maintain()
{
sz = ch[0] -> sz + ch[1] -> sz + 1;
sum = ((ch[0] -> sum % mod + v % mod) % mod + ch[1] -> sum % mod) % mod;
}
void pushdown();
int dir() { return f -> ch[1] == this; }
bool isroot() { return f -> ch[0] != this && f -> ch[1] != this; }
}T[SZ], *null, *tree[SZ];
int Tcnt = 0;
node* newnode(int x)
{
node *k = T + (Tcnt ++);
k -> ch[0] = k -> ch[1] = k -> f = null;
k -> sz = 1;
k -> v = k -> sum = x;
k -> add = 0;
k -> c = 1;
k -> rev = 0;
return k;
}
void rotate(node *p)
{
int d = p -> dir();
node *fa = p -> f;
p -> f = fa -> f;
if(!fa -> isroot()) p -> f -> ch[fa -> dir()] = p;
fa -> ch[d] = p -> ch[d ^ 1];
if(fa -> ch[d] != null) fa -> ch[d] -> f = fa;
p -> setc(fa,d ^ 1);
fa -> maintain(); p -> maintain();
}
void pushrev(node *p) { if(p == null) return ; swap(p -> ch[0],p -> ch[1]); p -> rev ^= 1; }
void pushchange(node *p,int c,int add)
{
p -> v = ((c * p -> v) % mod + add) % mod;
p -> c = (c * (p -> c % mod)) % mod;
p -> add = ((c * p -> add) % mod + add) % mod;
p -> sum = ((c * p -> sum) % mod + (add * p -> sz) % mod) % mod;
}
void node :: pushdown()
{
if(rev) { pushrev(ch[0]); pushrev(ch[1]); rev ^= 1; }
if(add || c != 1)
{
pushchange(ch[0],c,add);
pushchange(ch[1],c,add);
add = 0; c = 1;
}
}
node *S[SZ];
void pushpath(node *p)
{
int top = 0;
/* node *m = p;
while(!m -> isroot())
{
if(m -> ch[0] != null)
{
m = m -> ch[0];
}
else if(m -> ch[1] != null)
}*/
while(!p -> isroot()) S[++ top] = p,p = p -> f;
S[++ top] = p;
while(top) S[top --] -> pushdown();
}
void splay(node *p)
{
pushpath(p);
while(!p -> isroot())
{
if(p -> f -> isroot()) rotate(p);
else
{
if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
else rotate(p),rotate(p);
}
}
p -> maintain();
}
void access(node *p)
{
node *last = null;
while(p != null)
{
splay(p);
p -> ch[1] = last; p -> maintain();
last = p;
p = p -> f;
}
}
void toroot(node *p)
{
access(p);
splay(p);
pushrev(p);
}
void link(node *u,node *v)
{
toroot(u);
u -> f = v;
}
void cut(node *u,node *v)
{
toroot(u);
access(v);
splay(v);
v -> ch[0] = u -> f = null;
}
void change(node *u,node *v,LL c,LL add)
{
toroot(u);
access(v);
splay(v);
pushchange(v,c,add);
}
LL ask_sum(node *u,node *v)
{
toroot(u);
access(v);
splay(v);
return v -> sum;
}
void init()
{
null = newnode(0);
null -> sz = null -> sum = null -> v = 0;
}
void dfs(node *p)
{
if(p == null) return ;
printf("%d %d %d\n",p - T,p -> v,p -> sum);
dfs(p -> ch[0]);
dfs(p -> ch[1]);
}
int main()
{
// freopen("2631.in","r",stdin);
// freopen("out.txt","w",stdout);
init();
int n,q;
scanf("%d%d",&n,&q);
for(int i = 1;i <= n;i ++)
tree[i] = newnode(1);
for(int i = 1;i < n;i ++)
{
int u,v;
scanf("%d%d",&u,&v);
link(tree[u],tree[v]);
}
while(q --)
{
char opt[2];
scanf("%s",opt);
if(opt[0] == '+')
{
int u,v,add;
scanf("%d%d%d",&u,&v,&add);
add %= mod;
change(tree[u],tree[v],1,add);
}
else if(opt[0] == '-')
{
int u1,v1,u2,v2;
scanf("%d%d%d%d",&u1,&v1,&u2,&v2);
cut(tree[u1],tree[v1]);
link(tree[u2],tree[v2]);
}
else if(opt[0] == '*')
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
c %= mod;
change(tree[u],tree[v],c,0);
}
else
{
int u,v;
scanf("%d%d",&u,&v);
printf("%u\n",ask_sum(tree[u],tree[v]));
}
// for(int i = 1;i <= n;i ++) dfs(tree[i]), puts("");
}
return 0;
}
/*
7 3
2 1
3 1
4 2
5 1
6 5
7 1
+ 5 4 691
* 4 3 4319
/ 4 6
*/