BZOJ 2631 tree
2017.11.20
2017.11.20
维护一颗树,支持:
这题LCT维护下。
重点是这题卡longlong......需要压成unsigned int才能过......
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
#define MO 51061
int n,q,ia,ib,ic,siz[N],c[2][N],fa[N];
unsigned int v[N],t[N],lzu[N],lzm[N];
bool rev[N];
int to[N<<1],nex[N<<1],head[N],tot;
inline int RI()
{
int ret=0;
char tmp=getchar();
while(tmp<'0'||tmp>'9') tmp=getchar();
while(tmp>='0'&&tmp<='9') ret=ret*10+tmp-'0',tmp=getchar();
return ret;
}
inline void AE(int tx,int ty) {to[++tot]=ty,nex[tot]=head[tx],head[tx]=tot;}
void DFS(int pos,int pre)
{
for(int i=head[pos];i;i=nex[i])
if(to[i]!=pre)
fa[to[i]]=pos,DFS(to[i],pos);
}
inline bool isroot(int pos) {return c[0][fa[pos]]!=pos&&c[1][fa[pos]]!=pos;}
inline void pushup(int pos)
{
siz[pos]=siz[c[0][pos]]+siz[c[1][pos]]+1;
v[pos]=(v[c[0][pos]]+v[c[1][pos]]+t[pos])%MO;
}
inline void pushdown(int pos)
{
if(lzm[pos]!=1)
{
v[c[0][pos]]=(v[c[0][pos]]*lzm[pos])%MO,v[c[1][pos]]=(v[c[1][pos]]*lzm[pos])%MO;
t[c[0][pos]]=(t[c[0][pos]]*lzm[pos])%MO,t[c[1][pos]]=(t[c[1][pos]]*lzm[pos])%MO;
lzm[c[0][pos]]=(lzm[c[0][pos]]*lzm[pos])%MO,lzm[c[1][pos]]=(lzm[c[1][pos]]*lzm[pos])%MO;
lzu[c[0][pos]]=(lzu[c[0][pos]]*lzm[pos])%MO,lzu[c[1][pos]]=(lzu[c[1][pos]]*lzm[pos])%MO;
lzm[pos]=1;
}
if(lzu[pos])
{
v[c[0][pos]]=(v[c[0][pos]]+lzu[pos]*siz[c[0][pos]])%MO,v[c[1][pos]]=(v[c[1][pos]]+lzu[pos]*siz[c[1][pos]])%MO;
t[c[0][pos]]=(t[c[0][pos]]+lzu[pos])%MO,t[c[1][pos]]=(t[c[1][pos]]+lzu[pos])%MO;
lzu[c[0][pos]]=(lzu[c[0][pos]]+lzu[pos])%MO,lzu[c[1][pos]]=(lzu[c[1][pos]]+lzu[pos])%MO;
lzu[pos]=0;
}
if(rev[pos])
{
swap(c[0][c[0][pos]],c[1][c[0][pos]]);
swap(c[0][c[1][pos]],c[1][c[1][pos]]);
rev[c[0][pos]]^=1,rev[c[1][pos]]^=1;
rev[pos]=false;
}
}
void init(int pos)
{
if(!isroot(pos)) init(fa[pos]);
pushdown(pos);
}
inline void rotate(int tx)
{
int ty=fa[tx],tz=fa[ty],tl=(c[1][ty]==tx),tr=tl^1;//c[1][ty]==tx
if(!isroot(ty)) c[c[1][tz]==ty][tz]=tx;//c[1][tz]==ty
fa[tx]=tz,fa[ty]=tx;
fa[c[tr][tx]]=ty,c[tl][ty]=c[tr][tx],c[tr][tx]=ty;
pushup(ty),pushup(tx);
}
inline void splay(int tx)
{
init(tx);//init(tx);
while(!isroot(tx))
{
int ty=fa[tx],tz=fa[ty];
if(!isroot(ty))
{
if((c[0][ty]==tx)^(c[0][tz]==ty)) rotate(tx);
else rotate(ty);
}
rotate(tx);
}
}
inline void access(int pos)
{
//init(pos); NOT NEEDED
int tmp=0;
while(pos)
{
splay(pos);
c[1][pos]=tmp;
pushup(pos);
tmp=pos,pos=fa[pos];
}
}
inline void chroot(int pos)
{
access(pos),splay(pos);
swap(c[0][pos],c[1][pos]);
rev[pos]^=1;
}
inline void link(int tx,int ty)
{
chroot(tx),fa[tx]=ty;
}
inline void cut(int tx,int ty)
{
//chroot(tx),splay(ty); WRONG!
chroot(tx),access(ty),splay(ty);
c[0][ty]=fa[tx]=0;
pushup(ty);
}
inline void add(int tx,int ty,unsigned int tz)
{
chroot(tx),access(ty),splay(ty);
t[ty]=(t[ty]+tz)%MO,v[ty]=(v[ty]+1ll*tz*siz[ty])%MO,lzu[ty]=(lzu[ty]+tz)%MO;
}
inline void mul(int tx,int ty,int tz)
{
chroot(tx),access(ty),splay(ty);
t[ty]=(t[ty]*tz)%MO,v[ty]=(v[ty]*tz)%MO,lzu[ty]=(lzu[ty]*tz)%MO,lzm[ty]=(lzm[ty]*tz)%MO;
}
inline long long query(int tx,int ty)
{
chroot(tx),access(ty),splay(ty);
return v[ty]%MO;
}
int main()
{
n=RI(),q=RI();
for(int i=2;i<=n;++i) ia=RI(),ib=RI(),AE(ia,ib),AE(ib,ia);
for(int i=1;i<=n;++i) v[i]=t[i]=1;
DFS(1,0);
while(q--)
{
char md=getchar();
while(md!='+'&&md!='-'&&md!='*'&&md!='/') md=getchar();
switch(md)
{
case '+': ia=RI(),ib=RI(),ic=RI(),add(ia,ib,ic);break;
case '-': ia=RI(),ib=RI(),cut(ia,ib),ia=RI(),ib=RI(),link(ia,ib);break;
case '*': ia=RI(),ib=RI(),ic=RI(),mul(ia,ib,ic);break;
case '/': ia=RI(),ib=RI(),printf("%u\n",query(ia,ib));break;
}
}
}