1. 程式人生 > >2018.10.08【BZOJ2631】tree(LCT)

2018.10.08【BZOJ2631】tree(LCT)

解析:

其實就是這道題放到了LCTLCT上來做,其實操作基本都是一樣的。

拿來做LCTLCT的練手題還不錯。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
ll getint(){
	re ll num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(
isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline void outint(int a){ static char ch[23]; if(a==0)pc('0'); while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } inline char getop(){ re char c; while('+'!=(c=gc())&&'-'!=c&&'*'!=c&&'/'
!=c); return c; } cs ll mod=51061; typedef struct splay_node *point; struct splay_node{ point son[2],fa; bool tag; int mul,add,sum,val,siz; splay_node(){ siz=1; son[0]=son[1]=fa=NULL; tag=add=0; mul=sum=val=1; } point &lc(){return son[0];} point &rc(){return son[1];} bool isroot
(){return !fa||(fa->son[0]!=this&&fa->son[1]!=this);} bool which(){return fa->son[1]==this;} void pushnow(int Mul,int Add){ sum=(1ll*sum*Mul%mod+siz*Add%mod)%mod; val=(1ll*val*Mul%mod+Add)%mod; add=(1ll*add*Mul%mod+Add)%mod; mul=1ll*mul*Mul%mod; } void pushdown(){ if(tag){ swap(son[0],son[1]); if(son[0])son[0]->tag^=1; if(son[1])son[1]->tag^=1; tag=0; } if(mul!=1||add){ if(son[0])son[0]->pushnow(mul,add); if(son[1])son[1]->pushnow(mul,add); mul=1,add=0; } } void pushup(){ siz=(son[0]?son[0]->siz:0)+(son[1]?son[1]->siz:0)+1; sum=((son[0]?son[0]->sum:0)+(son[1]?son[1]->sum:0)+val)%mod; } }; cs int N=100005; struct Link_Cut_Tree{ splay_node ttt[N]; void Rotate(point now){ point Fa=now->fa,FA=Fa->fa; bool pos=now->which(); if(FA&&!Fa->isroot())FA->son[Fa->which()]=now; Fa->fa=now; now->fa=FA; Fa->son[pos]=now->son[!pos]; if(Fa->son[pos])Fa->son[pos]->fa=Fa; now->son[!pos]=Fa; Fa->pushup(); now->pushup(); } void Splay(point now){ static point q[N]; static int qn; q[qn=1]=now; for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa; for(int re i=qn;i;--i)q[i]->pushdown(); for(point Fa;!now->isroot();Rotate(now)) if(!(Fa=now->fa)->isroot())Rotate(Fa->which()==now->which()?Fa:now); } void access(point now){ for(point son=NULL;now;son=now,now=now->fa) Splay(now),now->rc()=son,now->pushup(); } void makeroot(point now){ access(now),Splay(now); now->tag^=1; } void link(point u,point v){ makeroot(u),u->fa=v; } void link(int u,int v){link(&ttt[u],&ttt[v]);} void cut(point u,point v){ makeroot(u),access(v),Splay(v); v->lc()=u->fa=NULL; } void cut(int u,int v){cut(&ttt[u],&ttt[v]);} void add(point u,point v,int val){ makeroot(u),access(v),Splay(v); v->pushnow(1,val); } void add(int u,int v,int val){add(&ttt[u],&ttt[v],val);} void mul(point u,point v,int val){ makeroot(u),access(v),Splay(v); v->pushnow(val,0); } void mul(int u,int v,int val){mul(&ttt[u],&ttt[v],val);} int query(point u,point v){ makeroot(u); access(v); Splay(v); return v->sum; } int query(int u,int v){return query(&ttt[u],&ttt[v]);} }LCT; int n,q; signed main(){ n=getint(),q=getint(); for(int re i=1;i<n;++i){ int u=getint(),v=getint(); LCT.link(u,v); } while(q--){ char op=getop(); int u=getint(),v=getint(); switch(op){ case '+':{ int val=getint(); LCT.add(u,v,val); break; } case '-':{ LCT.cut(u,v); u=getint(),v=getint(); LCT.link(u,v); break; } case '*':{ int val=getint(); LCT.mul(u,v,val); break; } case '/':{ outint(LCT.query(u,v)),pc('\n'); break; } } } return 0; }