2631: tree
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 3569 Solved: 1191
Description
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
*1 3 4
/ 1 1
Sample Output
4
HINT
数据规模和约定
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4
真-模板题!
两个标记像那道线段树一样写。
然后一直T的原因:upgrade的时候把原来树结构上面的所有Auxiliary Tree都pushdown了!!!!上一道题居然没有T。。。。
然后输出的时候!!一定要注意特判0的情况!!!!!!!!!!!!!!
另外这道题用unsigned可以节省一半的时间。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef unsigned LL;
const int INF=0x3f3f3f3f;
const int maxn = 100005;
const LL mod = 51061;
struct Node
{
int fa;
int ch[2];
bool isroot;
LL size;
LL sum,val;
LL mult,add;
int rev;
Node()
{
fa=ch[0]=ch[1]=0;
size=1u;
sum=0u,val=1u;
mult=1u; add=0u;
rev=0;
isroot=true;
}
}node[maxn];
#define fa(x) node[x].fa
#define ch(x,d) node[x].ch[d]
#define isroot(x) node[x].isroot
#define size(x) node[x].size
#define sum(x) node[x].sum
#define val(x) node[x].val
#define mult(x) node[x].mult
#define add(x) node[x].add
#define rev(x) node[x].rev
inline void update(int x)
{
size(x)=1u; sum(x)=val(x);
if(ch(x,0)) size(x)+=size(ch(x,0)) , sum(x)+=sum(ch(x,0));
if(ch(x,1)) size(x)+=size(ch(x,1)) , sum(x)+=sum(ch(x,1));
size(x)%=mod; sum(x)%=mod;
}
inline void rotate(int x)
{
int y=fa(x),z=fa(y);
int l=(ch(y,1)==x),r=l^1;
if(isroot(y)) isroot(y)=false,isroot(x)=true;
else ch(z,ch(z,1)==y)=x;
fa(ch(x,r))=y; fa(y)=x; fa(x)=z;
ch(y,l)=ch(x,r); ch(x,r)=y;
update(y); update(x);
}
inline void pushdown(int x)
{
if(!x) return;
if(rev(x))
{
swap(ch(x,0),ch(x,1));
if(ch(x,0)) rev(ch(x,0))^=1;
if(ch(x,1)) rev(ch(x,1))^=1;
rev(x)^=1;
}
if(ch(x,0))
{
sum(ch(x,0)) = (sum(ch(x,0))*mult(x)+size(ch(x,0))*add(x)%mod) % mod;
val(ch(x,0)) = (val(ch(x,0))*mult(x) + add(x)) % mod;
mult(ch(x,0)) = mult(ch(x,0))*mult(x) % mod;
add(ch(x,0)) = (add(ch(x,0))*mult(x)+add(x)) % mod;
}
if(ch(x,1))
{
sum(ch(x,1)) = (sum(ch(x,1))*mult(x)+size(ch(x,1))*add(x)%mod) % mod;
val(ch(x,1)) = (val(ch(x,1))*mult(x) + add(x)) % mod;
mult(ch(x,1)) = mult(ch(x,1))*mult(x) % mod;
add(ch(x,1)) = (add(ch(x,1))*mult(x)+add(x)) % mod;
}
mult(x)=1u; add(x)=0u;
}
int sta[maxn];
int top;
inline void upgrade(int x)
{
while(!isroot(x))
{
sta[++top]=x;
x=fa(x);
}
sta[++top]=x;
while(top) pushdown(sta[top--]);
}
inline void splay(int x)
{
upgrade(x);
while(!isroot(x))
{
int y=fa(x),z=fa(y);
if(!isroot(y))
if(ch(y,0)==x ^ ch(z,0)==y) rotate(x);
else rotate(y);
rotate(x);
}
}
inline int access(int x)
{
int y=0;
do
{
splay(x);
isroot(ch(x,1))=true;
isroot(ch(x,1)=y)=false;
update(x);
x=fa(y=x);
}while(x);
return y;
}
inline void makeroot(int u)
{
int rt=access(u);
rev(rt)^=1;
}
void cut(int u,int v)
{
makeroot(u);
access(v); splay(v);
isroot(ch(v,0))=true;
fa(ch(v,0))=0; ch(v,0)=0;
update(v);
}
void join(int u,int v)
{
access(u); splay(u);
rev(u)^=1;
fa(u)=v;
}
void modify(int u,int v,LL ad,LL mul)
{
ad%=mod; mul%=mod;
makeroot(u);
access(v); splay(v);
sum(v) = (sum(v)*mul + size(v)*ad%mod) % mod;
val(v) = (val(v)*mul+ad) % mod;
mult(v) = (mult(v)*mul) % mod;
add(v) = (add(v)*mul+ad) % mod;
}
LL query(int u,int v)
{
makeroot(u);
access(v); splay(v);
return sum(v);
}
inline char readchar()
{
char c=getchar();
while(c^'+' && c^'-' && c^'*' && c^'/') c=getchar();
return c;
}
inline void read(int &x)
{
x=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
{
x*=10; x+=c-'0';
c=getchar();
}
}
char ans[15];
int pos;
inline void readout(LL x)
{
if(!x) // extremely important !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{
putchar('0');
putchar('\n');
return;
}
pos=0;
while(x)
{
ans[++pos]=x%10u + '0';
x/=10u;
}
while(pos)
{
putchar(ans[pos]);
pos--;
}
putchar('\n');
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
#endif
int n,q;
read(n),read(q);
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
join(x,y);
}
for(int i=1;i<=q;i++)
{
char c=readchar();
int u,v,x,y;
read(u),read(v);
switch(c)
{
case '+': read(x);
modify(u,v,x,1);
break;
case '*': read(x);
modify(u,v,0,x);
break;
case '-': read(x),read(y);
cut(u,v);
join(x,y);
break;
case '/': readout(query(u,v)); break;
}
}
return 0;
}