洛谷P1501【国家集训队】Tree_II

题面

题解

LCT维护链上求和,下放懒标记模板。
记得先乘后加即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<bits/stdc++.h>
#define RG register
#define file(x) freopen(#x".in", "rb", stdin);freopen(#x".out", "w+", stdout);
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std;

inline int read()
{
int data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
return data*w;
}

const int maxn(100010), mod(51061);
int n, q;
int val[maxn], sum[maxn], lzmul[maxn], lzadd[maxn], fa[maxn], son[2][maxn], st[maxn], top, size[maxn];
bool rev[maxn];

inline bool isroot(int x) { return son[0][fa[x]]!=x && son[1][fa[x]]!=x; }
inline bool get_son(int x) { return son[1][fa[x]]==x; }
inline void update(int x) { sum[x]=(1ll*sum[son[0][x]]+sum[son[1][x]]+val[x])%mod; size[x]=size[son[0][x]]+size[son[1][x]]+1; }
inline void psmul(int x, int v)
{
if(x==0) return;
sum[x]=1ll*sum[x]*v%mod;
lzmul[x]=1ll*lzmul[x]*v%mod;
val[x]=1ll*val[x]*v%mod;
lzadd[x]=1ll*lzadd[x]*v%mod;
}
inline void psadd(int x, int v)
{
if(x==0) return;
sum[x]=(1ll*sum[x]+1ll*size[x]*v)%mod;
val[x]=(1ll*val[x]+v)%mod;
lzadd[x]=(1ll*lzadd[x]+v)%mod;
}
inline void pushdown(int x)
{
if(lzmul[x]!=1) psmul(son[0][x], lzmul[x]), psmul(son[1][x], lzmul[x]), lzmul[x]=1;
if(lzadd[x]) psadd(son[0][x], lzadd[x]), psadd(son[1][x], lzadd[x]), lzadd[x]=0;
if(rev[x])
{
if(son[0][x]) rev[son[0][x]]^=1;
if(son[1][x]) rev[son[1][x]]^=1;
rev[x]=0;
swap(son[0][x], son[1][x]);
}
}
inline void rotate(int x)
{
int f=fa[x], g=fa[f], l=get_son(x), r=l^1;
if(!isroot(f)) son[get_son(f)][g]=x;
fa[x]=g; fa[f]=x; fa[son[r][x]]=f;
son[l][f]=son[r][x]; son[r][x]=f;
update(f); update(x);
}
inline void splay(int x)
{
top=1; st[top]=x;
for(RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
for(RG int i=top;i;i--) pushdown(st[i]);
for(;!isroot(x);rotate(x)) if(!isroot(fa[x])) rotate(get_son(fa[x])^get_son(x)?x:fa[x]);
}
inline void access(int x) { for(RG int t=0;x;t=x, x=fa[x]) splay(x), son[1][x]=t, update(x); }
inline void makeroot(int x) { access(x); splay(x); rev[x]^=1; }
inline void split(int x, int y) { makeroot(x); access(y); splay(y); }
inline void link(int x, int y) { makeroot(x); fa[x]=y; }
inline void cut(int x, int y) { split(x, y); if(son[0][y]==x) son[0][y]=0; fa[x]=0; }
inline void mul(int x, int y, int v) { split(x, y); psmul(y, v); }
inline void add(int x, int y, int v) { split(x, y); psadd(y, v); }
inline int query(int x, int y) { split(x, y); return sum[y]; }

int a, b, c, d;
char s[3];
int main()
{
n=read(); q=read();
for(RG int i=1;i<=n;i++) val[i]=size[i]=lzmul[i]=1;
for(RG int i=1;i<n;i++) a=read(), b=read(), link(a, b);
while(q--)
{
scanf("%s", s);
a=read(); b=read();
if(s[0]=='+') c=read(), add(a, b, c);
else if(s[0]=='-') c=read(), d=read(), cut(a, b), link(c, d);
else if(s[0]=='*') c=read(), mul(a, b, c);
else printf("%d\n", query(a, b));
}
return 0;
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×