%%%PoPoQQQ:http://blog.csdn.net/popoqqq/article/details/40823659
第四个操作怎么办?!做过2752就好了
PS.这么一打,发现自己以前LCT的版子好像有小问题,这就尴尬了...
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define V G[p].v
using namespace std;
typedef long long ll;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=50005;
ll Gcd(ll a,ll b){
if (a<b) return Gcd(b,a);
return b?Gcd(b,a%b):a;
}
struct Splay{
struct node{
node *p,*ch[2],*fat;
int size,rev;
ll f,exp,lsum,rsum,val,sum;
bool dir() { return this==p->ch[1]; }
void setc(node *c,int d) { ch[d]=c; c->p=this; }
void update(){
size=ch[0]->size+ch[1]->size+1;
sum=ch[0]->sum+ch[1]->sum+val;
exp=ch[0]->exp+ch[1]->exp+ch[0]->lsum*(ch[1]->size+1)+ch[1]->rsum*(ch[0]->size+1)+val*(ch[0]->size+1)*(ch[1]->size+1);
lsum=ch[0]->lsum+ch[1]->lsum+(ch[1]->sum+val)*(ch[0]->size+1);
rsum=(ch[0]->sum+val)*(ch[1]->size+1)+ch[0]->rsum+ch[1]->rsum;
}
void reverse(){
rev^=1;
swap(ch[0],ch[1]);
swap(lsum,rsum);
}
void modify(ll x){
f+=x;
val+=x;
sum+=size*x;
lsum+=x*size*(size+1)/2; rsum+=x*size*(size+1)/2;
exp+=x*size*(size+1)*(size+2)/6;
}
void pushdown(node *null)
{
if (rev)
{
if (ch[0]!=null) ch[0]->reverse();
if (ch[1]!=null) ch[1]->reverse();
rev=0;
}
if (f)
{
if (ch[0]!=null) ch[0]->modify(f);
if (ch[1]!=null) ch[1]->modify(f);
f=0;
}
}
}*null;
node Mem[N];
Splay(){
null=Mem; null->p=null->ch[0]=null->ch[1]=null; null->size=null->exp=null->lsum=null->rsum=null->sum=0;
}
void rot(node *x){
if (x==null) return;
bool d=x->dir(); node *p=x->p;
if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat);
}
node *stk[N];int pnt;
void splay(node *x){
node *y=x; pnt=0;
while (y!=null) stk[++pnt]=y,y=y->p;
for (int i=pnt;i;i--)
stk[i]->pushdown(null);
while (x->p!=null)
if (x->p->p==null)
rot(x);
else
(x->dir()==x->p->dir())?(rot(x->p),rot(x)):(rot(x),rot(x));
}
node *Access(node *x){
node *y=null;
while (x!=null)
{
splay(x);
x->ch[1]->p=null; x->ch[1]->fat=x;
x->setc(y,1); y->fat=null;
x->update();
y=x; x=x->fat;
}
return y;
}
void Link(node *x,node *y){
if (x==y || Jud(x,y)) return;
Access(x)->reverse();
splay(x); x->fat=y;
Access(x);
}
node *Root(node *x){
Access(x); splay(x);
node *y=x;
while (y!=null) y->pushdown(null),x=y,y=y->ch[0];
return x;
}
bool Jud(node *x,node *y){
return Root(x)==Root(y);
}
void Cut(node *x,node *y){
if (x==y || !Jud(x,y)) return;
Access(x)->reverse();
Access(y); splay(y);
if (y->ch[0]==x && x->ch[1]==null)
{
y->ch[0]->p=null; y->ch[0]=null;
y->fat=null; y->update();
}
}
void Modify(node *x,node *y,ll d){
if (!Jud(x,y)) return;
Access(x)->reverse();
return Access(y)->modify(d);
}
pair<ll,int> Query(node *x,node *y){
Access(x)->reverse();
node *z=Access(y);
return pair<ll,int>(z->exp,z->size);
}
}LCT;
int n;
Splay::node *pos[N];
inline void Init(int n){
for (int i=1;i<=n;i++)
{
pos[i]=LCT.Mem+i; pos[i]->size=1;
pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=pos[i]->fat=LCT.null;
}
}
ll iP,iQ,D;
struct edge{
int u,v,next;
};
edge G[N*2];
int head[N],num;
inline void add(int u,int v,int p)
{
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
inline int dfs(int u,int fa)
{
if (!fa) pos[u]->fat=LCT.null; else pos[u]->fat=pos[fa];
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u);
}
int main()
{
int ia,iu,iv,Q,order,isize;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); Init(n);
read(Q);
for (int i=1;i<=n;i++)
read(ia),pos[i]->val=ia,pos[i]->update();
for (int i=1;i<n;i++)
{
read(iu),read(iv);
// LCT.Link(pos[iu],pos[iv]);
add(iu,iv,++num),add(iv,iu,++num);
}
dfs(1,0);
while (Q--)
{
read(order); read(iu); read(iv);
if (order==1)
LCT.Cut(pos[iu],pos[iv]);
else if (order==2)
LCT.Link(pos[iu],pos[iv]);
else if (order==3)
read(ia),LCT.Modify(pos[iu],pos[iv],ia);
else if (order==4)
{
if (!LCT.Jud(pos[iu],pos[iv]))
printf("-1\n");
else
{
pair<ll,int> itmp=LCT.Query(pos[iu],pos[iv]);
iP=itmp.first; isize=itmp.second;
iQ=(ll)isize*(isize+1)/2;
D=Gcd(iQ,iP);
iP/=D; iQ/=D;
printf("%lld/%lld\n",iP,iQ);
}
}
}
return 0;
}