[国家集训队] Tree2 题解
加边删边 \(LCT\),标记下放同 \(luogu\) 线段树 \(2\) 一题。
时间复杂度 \(O(n\log n)\),第一次交的时候我维护 \(sum\) 不维护 \(sz\ WA\) 完了。
#include<bits/stdc++.h>
#define int long long
#define fa(x) lct[x].fa
#define fl(x) lct[x].fl
#define ad(x) lct[x].ad
#define tm(x) lct[x].tm
#define id(x) lct[x].id
#define sz(x) lct[x].sz
#define val(x) lct[x].val
#define sum(x) lct[x].sum
#define sn(x,i) lct[x].sn[i]
#define inf 1000000000
using namespace std;
const int N=100005,p=51061;
struct node{
int sn[2],fa,fl,ad,tm,val,sum,id,sz;
}lct[N];int n,m,tp,st[N];
int check(int x){
return sn(fa(x),0)!=x&&sn(fa(x),1)!=x;
}int chksn(int x){
return sn(fa(x),1)==x;
}void push_up(int x){
sum(x)=(sum(sn(x,0))+sum(sn(x,1))+val(x))%p;
sz(x)=(sz(sn(x,0))+sz(sn(x,1))+1)%p;
}void down(int x,int a,int t){
if(!x) return;
val(x)=(val(x)*t+a)%p;
sum(x)=(sum(x)*t+a*sz(x))%p;
ad(x)=(ad(x)*t+a)%p;
tm(x)=tm(x)*t%p;
}void push_down(int x){
if(!x) return;
if(fl(x)){
fl(sn(x,0))^=1,fl(sn(x,1))^=1;
swap(sn(x,0),sn(x,1)),fl(x)=0;
}down(sn(x,0),ad(x),tm(x));
down(sn(x,1),ad(x),tm(x));
ad(x)=0,tm(x)=1;
}void rotate(int x){
int y=fa(x),z=fa(y),k=chksn(x);
if(!check(y))
sn(z,chksn(y))=x;
fa(x)=z,fa(y)=x,fa(sn(x,1-k))=y;
sn(y,k)=sn(x,1-k),sn(x,1-k)=y;
push_up(y);
}void splay(int x){
st[tp=1]=x;
for(int i=x;!check(i);i=fa(i)) st[++tp]=fa(i);
while(tp) push_down(st[tp--]);
while(!check(x)){
int y=fa(x),z=fa(y);
if(!check(y))
rotate(chksn(x)!=chksn(y)?x:y);
rotate(x);
}push_up(x);
}void access(int x){
for(int i=0;x;i=x,x=fa(x))
splay(x),sn(x,1)=i,push_up(x);
}void mk(int x){
access(x),splay(x),fl(x)^=1;
}void split(int x,int y){
mk(x),access(y),splay(y);
}void cut(int x,int y){
split(x,y),sn(y,0)=fa(x)=0;
}void link(int x,int y){
mk(x),access(y),fa(x)=y;
}signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) sum(i)=val(i)=sz(i)=tm(i)=1;
for(int i=1,x,y;i<n;i++) cin>>x>>y,link(x,y);
while(m--){
char opt;int x,y,z,w;cin>>opt>>x>>y;
if(opt=='+')
cin>>z,split(x,y),down(y,z,1);
if(opt=='-')
cin>>z>>w,cut(x,y),link(z,w);
if(opt=='*')
cin>>z,split(x,y),down(y,0,z);
if(opt=='/')
split(x,y),cout<<sum(y)<<"\n";
}return 0;
}

浙公网安备 33010602011771号