3091: 城市旅行
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1927 Solved: 631
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4 5
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4
Sample Output
16/3
6/1
6/1
HINT
对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N
题解
这题和BZOJ2752类似,只不过那个是在序列上而这个在链上,所以没做过2752的话可以先看看这里
我们发现每次询问其实就是算每个点对答案的贡献/C(n+1,2),也就是/(n+1)*n/2
所以每次只需要单独算每个点的贡献即可
然后每个点对答案的贡献就是a[i]*i*(n-i+1)
所以我们维护一个sum,一个siz,一个L=a[i]*i,一个R=a[i]*(n-i+1)
转移挺好想的(逃
代码(WA???)
//by 减维 #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<bitset> #include<set> #include<cmath> #include<vector> #include<set> #include<map> #include<ctime> #include<algorithm> #define ll long long #define il inline #define rg register #define db double #define mpr make_pair #define maxn 70005 #define inf (1<<30) #define eps 1e-8 #define pi 3.1415926535897932384626 using namespace std; inline int read() { int ret=0;bool fla=0;char ch=getchar(); while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘)ch=getchar(); if(ch==‘-‘){fla=1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){ret=ret*10+ch-‘0‘;ch=getchar();} return fla?-ret:ret; } ll n,m,fa[maxn],son[maxn][2],siz[maxn],val[maxn],sum[maxn],rev[maxn],mar[maxn],L[maxn],R[maxn],ans[maxn]; il ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);} il bool pdp(int x){return son[fa[x]][1]==x;} il bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;} il void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);swap(L[x],R[x]);} il void upda(int x) { siz[x]=siz[son[x][0]]+siz[son[x][1]]+1; sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x]; ans[x]=ans[son[x][0]]+ans[son[x][1]]+val[x]*(siz[son[x][0]]+1)*(siz[son[x][1]]+1)+L[son[x][0]]*(siz[son[x][1]]+1)+R[son[x][1]]*(siz[son[x][0]]+1); L[x]=L[son[x][0]]+L[son[x][1]]+val[x]*(siz[son[x][0]]+1)+sum[son[x][1]]*(siz[son[x][0]]+1); R[x]=R[son[x][1]]+R[son[x][0]]+val[x]*(siz[son[x][1]]+1)+sum[son[x][0]]*(siz[son[x][1]]+1); } il void add(int x,ll y) { mar[x]+=y; val[x]+=y; sum[x]+=y; ans[x]+=y*(siz[x]+1)*(siz[x]+2)*siz[x]/6; L[x]+=y*(siz[x]+1)*siz[x]/2; R[x]+=y*(siz[x]+1)*siz[x]/2; } il void pdn(int x) { if(rev[x]) { if(son[x][0]) rever(son[x][0]); if(son[x][1]) rever(son[x][1]); rev[x]=0; } if(mar[x]) { if(son[x][0]) add(son[x][0],mar[x]); if(son[x][1]) add(son[x][1],mar[x]); mar[x]=0; } } il void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);} il void rot(int x) { int f=fa[x],g=fa[f],o=pdp(x); if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g; son[f][o]=son[x][!o];fa[son[f][o]]=f; son[x][!o]=f;fa[f]=x; upda(f),upda(x); } il void splay(int x) { pd(x); for(;!isrt(x);rot(x)) if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x); } il void acc(int x) { for(int y=0;x;y=x,x=fa[x]) splay(x),son[x][1]=y,upda(x); } il int find(int x) { acc(x);splay(x); while(son[x][0]) pdn(x),x=son[x][0]; return x; } il void bert(int x){acc(x);splay(x);rever(x);} il void spli(int x,int y){bert(x);acc(y);splay(y);} il void cut(int x,int y){spli(x,y);fa[x]=son[y][0]=0;upda(y);} il void link(int x,int y){bert(x);fa[x]=y;} void dfs(int x) { if(son[x][0]) dfs(son[x][0]); printf("%d ",x); if(son[x][1]) dfs(son[x][1]); } void dfs2(int x) { if(son[x][0]) dfs2(son[x][0]); printf("%d ",sum[x]); if(son[x][1]) dfs2(son[x][1]); } int main() { n=read();m=read(); for(int i=1;i<=n;++i) val[i]=read(); for(int i=1,x,y;i<n;++i) x=read(),y=read(),link(x,y); for(int i=1,op,x,y,d;i<=m;++i) { op=read();x=read();y=read(); if(op==1){ if(find(x)==find(y)) cut(x,y); }else if(op==2){ if(find(x)!=find(y)) link(x,y); }else if(op==3){ d=read(); spli(x,y);add(y,d); }else{ if(find(x)!=find(y)) puts("-1"); else spli(x,y),printf("%lld/%lld\n",ans[y]/gcd(ans[y],siz[y]*(siz[y]+1)/2),(siz[y]+1)*siz[y]/2/gcd(ans[y],siz[y]*(siz[y]+1)/2)); } } return 0; }