lct模板题。
很长时间没有这么错了。。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
using namespace std;
const int N=100055;
const int mod=51061;
typedef unsigned int ll;
inline ll read()
{
ll ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
int n,m;
int fa[N],ch[N][2];
ll size[N],val[N],sum[N],add[N],mul[N];
bool rev[N];
bool isroot(int u)
{
return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;
}
void down(int u)
{
int l=ch[u][0],r=ch[u][1];
if (rev[u])
{
rev[l]^=1;rev[r]^=1;rev[u]^=1;
swap(ch[u][0],ch[u][1]);
}
if (mul[u]!=1)
{
mul[l]=mul[l]*mul[u]%mod,mul[r]=mul[r]*mul[u]%mod;
add[l]=add[l]*mul[u]%mod,add[r]=add[r]*mul[u]%mod;
sum[l]=sum[l]*mul[u]%mod,sum[r]=sum[r]*mul[u]%mod;
val[l]=val[l]*mul[u]%mod,val[r]=val[r]*mul[u]%mod;
mul[u]=1;
}
if (add[u])
{
add[l]=(add[l]+add[u])%mod,add[r]=(add[r]+add[u])%mod;
sum[l]=(sum[l]+size[l]*add[u])%mod;
sum[r]=(sum[r]+size[r]*add[u])%mod;
val[l]=(val[l]+add[u])%mod,val[r]=(val[r]+add[u])%mod;
add[u]=0;
}
}
void up(int x)
{
int l=ch[x][0],r=ch[x][1];
size[x]=size[l]+size[r]+1;
sum[x]=(val[x]+sum[l]+sum[r])%mod;
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
stack<int> s;
void splay(int x)
{
int y=x,z;
while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
while (!s.empty()) down(s.top()),s.pop();
while (!isroot(x))
{
y=fa[x],z=fa[y];
if (!isroot(y))
if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
rot(x);
}
up(x);
}
void access(int u)
{
int t=0;
while (u)
{
splay(u);
ch[u][1]=t;
t=u;u=fa[u];
}
}
void to_rt(int u)
{
access(u);splay(u);rev[u]^=1;
}
void link(int u,int v)
{
to_rt(u);fa[u]=v;
}
void cut(int u,int v)
{
to_rt(u);access(v);splay(v);fa[u]=ch[v][0]=0;
}
void cut_link()
{
int u1,v1,u2,v2;
u1=read();v1=read();u2=read();v2=read();
cut(u1,v1);link(u2,v2);
}
void link_add()
{
int u,v;ll c;
u=read(),v=read(),c=read();
to_rt(u);access(v);splay(v);
add[v]=(add[v]+c)%mod;sum[v]=(sum[v]+size[v]*c)%mod;val[v]=(val[v]+c)%mod;
}
void link_mul()
{
int u,v;ll c;
u=read(),v=read(),c=read();
to_rt(u);access(v);splay(v);
mul[v]=mul[v]*c%mod;sum[v]=sum[v]*c%mod;val[v]=val[v]*c%mod;add[v]=add[v]*c%mod;
}
void query()
{
int u,v;
u=read(),v=read();
to_rt(u);access(v);splay(v);
printf("%d\n",sum[v]);
}
int main()
{
n=read(),m=read();
for (int i=1;i<=n;i++) mul[i]=val[i]=sum[i]=size[i]=1;
int x,y;
for (int i=1;i<n;i++)
{
x=read(),y=read();
link(x,y);
}
char s[3];
while (m--)
{
scanf("%s",s);
switch(s[0])
{
case '+':link_add();break;
case '-':cut_link();break;
case '*':link_mul();break;
case '/':query();break;
}
}
return 0;
}
总结
1:split,取u~v这一条链,就是把u转到根,access(v),splay(v)之后就取出这条链了。
2:然后就是标记下传的情况,需要注意,下穿的时候更新的是孩子的数据,当前点事要在之前就是更新过才行。