LCT模板题
坑死我了。
首先会超int,这里就不知不觉wa了几次,之后还是WA,以为模板不行,改来改去还是WA。
最后发现数据范围结点下标没有说明.....改成最大范围的结点下标后终于A了
感觉还是得写个动态的模板啊。
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,102400000")
#define maxn 100005
#define maxm 1000005
#define INF 1000000007
#define LINF 1000000000000001LL
#define LL long long
#define MOD 51061
struct node
{
int to,next;
} edge[maxn<<1];
int head[maxn],esum;
inline void addedge(int u,int v)
{
edge[esum].to=v,edge[esum].next=head[u],head[u]=esum++;
}
int n,m;
int ch[maxn][2],pre[maxn];
int chnum[maxn];
bool rev[maxn];
LL val[maxn],add[maxn],mul[maxn],sum[maxn];
bool rt[maxn];
void dfs(int u)
{
for(int i=head[u],v; ~i; i=edge[i].next)
{
v=edge[i].to;
if(pre[v]) continue;
pre[v]=u;
dfs(v);
}
}
inline void update(int x,LL a,LL b)
{
add[x]=(add[x]*a+b)%MOD;
val[x]=(val[x]*a+b)%MOD;
sum[x]=(sum[x]*a+b*(LL)chnum[x])%MOD;
mul[x]=(mul[x]*a)%MOD;
}
inline void push_up(int x)
{
sum[x]=val[x],chnum[x]=1;
chnum[x]+=chnum[ch[x][0]],sum[x]+=sum[ch[x][0]];
chnum[x]+=chnum[ch[x][1]],sum[x]+=sum[ch[x][1]];
sum[x]%=MOD;
}
inline void push_down(int x)
{
if (rev[x])
{
swap(ch[x][0],ch[x][1]);
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
rev[x] = 0;
}
if(mul[x]!=1||add[x])
{
update(ch[x][0],mul[x],add[x]);
update(ch[x][1],mul[x],add[x]);
mul[x]=1,add[x]=0;
}
}
///旋转操作,c=0左旋,c=1右旋
inline void Rotate(int x,int c)
{
int y=pre[x],z=pre[y];
ch[y][!c]=ch[x][c];
pre[ch[x][c]]=y;
pre[x]=z;
if(ch[z][0]==y) ch[z][0]=x;
if(ch[z][1]==y) ch[z][1]=x;
ch[x][c]=y,pre[y]=x;
if(rt[y]) rt[y]=0,rt[x]=1;
push_up(y);
}
///将结点x转到结点tag的下面
inline void Splay(int x)
{
int y,z;
while(!rt[x])
{
if(rt[y=pre[x]])
{
push_down(y),push_down(x);
if(ch[y][0]==x) Rotate(x,1);
else Rotate(x,0);
}
else
{
z=pre[y];
push_down(z),push_down(y),push_down(x);
if(ch[z][0]==y)
{
if(ch[y][0]==x)
Rotate(y,1),Rotate(x,1);
else Rotate(x,0),Rotate(x,1);
}
else
{
if(ch[y][0]==x)
Rotate(x,1),Rotate(x,0);
else Rotate(y,0),Rotate(x,0);
}
}
}
push_up(x);
}
///将u到root的路径转换成实边
///返回u所在树的根结点
int Access(int u)
{
int v=0;
for(; u; u=pre[v=u])
{
Splay(u);///旋转之后,若u到根都是实边就可直接跳出
push_down(u);
rt[ch[u][1]]=1, rt[ch[u][1]=v]=0;
push_up(u);
}
return v;
}
int Lca(int u,int v)
{
Access(u);
return Access(v);
}
void MakeRoot(int u)
{
rev[Access(u)]^=1;
Splay(u);
}
///找到u所在树的根
int FindRoot(int u)
{
for(u=Access(u); push_down(u),ch[u][0]; u=ch[u][0]) ;
return u;
}
///先将u设为根,然后pre[u]=v,最后打通u到v所在树的根
bool Link(int u,int v)
{
// if(FindRoot(u)==FindRoot(v))
// {
// puts("-1");
// return 0;
// }
MakeRoot(u);
pre[u]=v;
Access(u);
return 1;
}
///先MR(x); 然后Access(y),Splay(y)。
///将u设为根节点,并使v和他的父节点断开
bool Cut(int u,int v)
{
MakeRoot(u);
Access(v);
Splay(v);
rt[ch[v][0]]=1;
pre[ch[v][0]]=pre[v];
pre[v]=ch[v][0]=0;
push_up(v);
return 1;
}
LL Query(int u,int v)
{
// if(FindRoot(u)!=FindRoot(v)) return -1;
MakeRoot(u);
Access(v);
Splay(v);
return sum[v];
}
bool Modify(int u,int v,int a,int b)
{
// if(FindRoot(u)!=FindRoot(v))
// {
// puts("-1");
// return 0;
// }
MakeRoot(u);
Access(v);
Splay(v);
update(v,(LL)a,(LL)b);
return 1;
}
int main()
{
char op[3];
int u,v,d,u1,v1;
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
while(~scanf("%d%d",&n,&m))
{
esum=0;
for(int i=0; i<maxn; i++)
{
rt[i]=1,mul[i]=1;
val[i]=1;
rev[i]=0;
ch[i][0]=ch[i][1]=pre[i]=0;
add[i]=0;
head[i]=-1;
}
for(int i=0; i<n-1; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
pre[u]=-1;
dfs(u);
pre[u]=0;
while(m--)
{
scanf("%s%d%d",op,&u,&v);
if(op[0]=='+')
{
scanf("%d",&d);
Modify(u,v,1,d);
}
else if(op[0]=='-')
{
scanf("%d%d",&u1,&v1);
Cut(u,v);
Link(u1,v1);
}
else if(op[0]=='*')
{
scanf("%d",&d);
Modify(u,v,d,0);
}
else printf("%lld\n",Query(u,v));
}
}
return 0;
}