您的位置:首页 > 其它

BZOJ3091: 城市旅行

2016-02-22 19:57 435 查看

Description

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lc ch[x][0]
#define rc ch[x][1]
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=50010;
ll f[maxn],sumv[maxn],sum[maxn],lsum[maxn],rsum[maxn],s[maxn],addv[maxn],val[maxn];
int pre[maxn],fa[maxn],ch[maxn][2],flip[maxn];
void Add(int x,ll v) {
if(!v||!x) return;
sumv[x]+=v*f[s[x]];
lsum[x]+=v*(1+s[x])*s[x]/2;
rsum[x]+=v*(1+s[x])*s[x]/2;
sum[x]+=v*s[x];
}
void maintain(int x) {
if(!x) return;
s[x]=s[lc]+s[rc]+1;
sum[x]=sum[lc]+sum[rc]+val[x];
sumv[x]=sumv[lc]+sumv[rc]+lsum[lc]*(s[rc]+1)+rsum[rc]*(s[lc]+1)+val[x]*(s[lc]+1)*(s[rc]+1);
lsum[x]=lsum[lc]+lsum[rc]+val[x]*(s[lc]+1)+sum[rc]*(s[lc]+1);
rsum[x]=rsum[rc]+rsum[lc]+val[x]*(s[rc]+1)+sum[lc]*(s[rc]+1);
Add(x,addv[x]);
}
void pushdown(int x) {
if(flip[x]) {
swap(lc,rc);
swap(lsum[lc],rsum[lc]);
swap(lsum[rc],rsum[rc]);
flip[lc]^=1;flip[rc]^=1;
flip[x]=0;
}
if(addv[x]) {
val[x]+=addv[x];addv[lc]+=addv[x];addv[rc]+=addv[x];
Add(lc,addv[x]);Add(rc,addv[x]);addv[x]=0;
}
}
void rotate(int x) {
int y=pre[x],z=pre[y],d=ch[y][0]==x;
ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
ch[z][ch[z][1]==y]=x;pre[x]=z;
ch[x][d]=y;pre[y]=x;maintain(y);
}
int S[maxn],top;
void splay(int x) {
for(int i=x;i;i=pre[i]) S[++top]=i;
if(top!=1) fa[x]=fa[S[top]],fa[S[top]]=0;
while(top) pushdown(S[top--]);
while(pre[x]) rotate(x);
maintain(x);
}
void access(int x) {
for(int y=0;x;x=fa[x]) {
splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
ch[x][1]=y;pre[y]=x;maintain(y=x);
}
}
void makeroot(int x) {
access(x);splay(x);flip[x]^=1;
maintain(x);
}
int find(int x) {
access(x);splay(x);
while(ch[x][0]) x=ch[x][0];
return x;
}
void link(int x,int y) {
makeroot(x);fa[x]=y;
}
void cut(int x,int y) {
makeroot(x);access(y);splay(y);
if(s[y]==2) {
pre[ch[y][0]]=0;ch[y][0]=0;
maintain(y);
}
}
ll gcd(ll x,ll y) {return !y?x:gcd(y,x%y);}
void query(int x,int y) {
makeroot(x);access(y);splay(y);
ll len=s[y]-1;len=(len+1)*(len+2)/2;
ll ans=sumv[y],t=gcd(len,ans);
printf("%lld/%lld\n",ans/t,len/t);
}
void update(int x,int y,ll v) {
makeroot(x);access(y);splay(y);
addv[y]+=v;Add(y,v);
}
int main() {
int n=read(),m=read();
f[1]=1;
rep(i,2,n) f[i]=f[i-1]+(ll)i*(i-1)/2+i;
rep(i,1,n) val[i]=read();
rep(i,1,n-1) link(read(),read());
while(m--) {
int t=read(),x=read(),y=read();
if(t==1) if(find(x)==find(y)) cut(x,y);
if(t==2) if(find(x)!=find(y)) link(x,y);
if(t==3) {
ll v=read();
if(find(x)==find(y)) update(x,y,v);
}
if(t==4) {
if(find(x)==find(y)) query(x,y);
else puts("-1");
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: