暴力碾标算系列
写一个时间复杂度基于直径长度的算法可以获得一百分的好成绩。
暴力(后面有std代码):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 50010
#define lint long long
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int fa[N],l[N];lint a[N];
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline lint gcd(lint x,lint y) { return x?gcd(y%x,x):y; }
inline int Makeroot(int x,int c=0)
{
for(int y=x;y;y=fa[y]) l[++c]=y;
for(;c;c--) fa[l[c]]=l[c-1];return 0;
}
inline int Getfa(int x) { while(fa[x]) x=fa[x];return x; }
inline int Link(int x,int y)
{
int c=0,z=y;Makeroot(x);
return Getfa(y)==x?0:fa[x]=y;
}
inline int Cut(int x,int y)
{
if(fa[x]==y) return fa[x]=0;
if(fa[y]==x) return fa[y]=0;
return 0;
}
inline int Update(int x,int y,int d)
{
Makeroot(x);if(Getfa(y)!=x) return 0;
while(y) a[y]+=d,y=fa[y];return 0;
}
inline int Query(int x,int y)
{
Makeroot(x);int c=0;while(y) l[++c]=y,y=fa[y];
if(l[c]!=x) return !printf("-1\n");lint ans=0,t=c*(c+1ll)/2;
for(int i=1;i<=c;i++) ans+=a[l[i]]*i*(c-i+1);
lint d=gcd(ans,t);return !printf("%lld/%lld\n",ans/d,t/d);
}
int main()
{
int n=inn(),m=inn();
for(int i=1;i<=n;i++) a[i]=inn();
for(int i=1;i<n;i++) Link(inn(),inn());
while(m--)
{
int opt=inn(),x=inn(),y=inn();
if(opt==1) Cut(x,y);
if(opt==2) Link(x,y);
if(opt==3) Update(x,y,inn());
if(opt==4) Query(x,y);
}
return 0;
}
std:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 50010
#define lint long long
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int ch[N][2],fa[N],rev[N],sz[N],pf[N];
lint val[N],s[N],ss[N],ps[N],ans[N],pt[N];
inline lint gcd(lint x,lint y) { return x?gcd(y%x,x):y; }
inline int gw(int x) { return ch[fa[x]][1]==x; }
inline lint init(int x,int v) { return val[x]=s[x]=ss[x]=ps[x]=ans[x]=v; }
inline int update_tags(int x,lint d)
{
s[x]+=sz[x]*d,pt[x]+=d,val[x]+=d,
ps[x]+=sz[x]*(sz[x]+1ll)/2*d,
ss[x]+=sz[x]*(sz[x]+1ll)/2*d,
ans[x]+=sz[x]*(sz[x]+1ll)/2*(sz[x]+2ll)/3*d;
return 0;
}
inline int push_down(int x)
{
if(rev[x])
{
if(ch[x][0]) ch[x][0][rev]^=1;
if(ch[x][1]) ch[x][1][rev]^=1;
swap(ch[x][0],ch[x][1]),rev[x]=0,
swap(ps[x],ss[x]);
}
if(pt[x])
{
if(ch[x][0]) update_tags(ch[x][0],pt[x]);
if(ch[x][1]) update_tags(ch[x][1],pt[x]);
pt[x]=0;
}
return 0;
}
inline int push_up(int x)
{
int lc=ch[x][0],rc=ch[x][1];push_down(lc),push_down(rc);
x[ans]=lc[ans]+rc[ans]+lc[ss]*(rc[sz]+1ll)+rc[ps]*(lc[sz]+1ll)+x[val]*(lc[sz]+1ll)*(rc[sz]+1ll),
x[ps]=lc[ps]+rc[ps]+(lc[s]+x[val])*(sz[rc]+1ll),x[ss]=rc[ss]+lc[ss]+(rc[s]+x[val])*(lc[sz]+1ll),
x[s]=lc[s]+rc[s]+x[val],x[sz]=lc[sz]+rc[sz]+1;return 0;
}
inline int setc(int x,int y,int z)
{
if(!x) return fa[y]=0;
ch[x][z]=y;if(y) fa[y]=x;
return push_up(x);
}
inline int rotate(int x)
{
int y=fa[x],z=fa[y],a=gw(x),b=gw(y),c=ch[x][a^1];
return swap(pf[x],pf[y]),setc(y,c,a),setc(x,y,a^1),setc(z,x,b);
}
inline int all_down(int x) { return (fa[x]?all_down(fa[x]):0),push_down(x); }
inline int splay(int x,int tar=0)
{
for(all_down(x);fa[x]^tar;rotate(x))
if(fa[fa[x]]^tar) rotate(gw(x)==gw(fa[x])?fa[x]:x);
return 0;
}
inline int expose(int x)
{
splay(x);int y=ch[x][1];if(!y) return 0;
return pf[y]=x,ch[x][1]=fa[y]=0,push_up(x);
}
inline int splice(int x)
{
splay(x);int y=pf[x];if(!y) return 0;
return expose(y),splay(y),setc(y,x,1),pf[x]=0,1;
}
inline int access(int x) { expose(x);while(splice(x));return 0; }
inline int evert(int x) { return access(x),splay(x),rev[x]^=1; }
inline int get_rt(int x)
{
access(x),splay(x);
while(ch[x][0]) push_down(x=ch[x][0]);
return splay(x),x;
}
inline int con(int x,int y) { return get_rt(x)==get_rt(y); }
inline int link(int x,int y) { return (!con(x,y))?evert(x),pf[x]=y:0; }
inline int cut(int x,int y)
{
evert(x),access(y),splay(x);
if(ch[x][1]==y) pf[y]=fa[y]=ch[x][1]=0,push_up(x);
return 0;
}
inline int update(int x,int y,int d)
{
if(!con(x,y)) return 0;
return evert(x),access(y),splay(x),update_tags(x,d);
}
inline int query(int x,int y)
{
if(!con(x,y)) return !printf("-1\n");
evert(x),access(y),splay(x);
lint t=sz[x]*(sz[x]+1ll)/2,d=gcd(ans[x],t);
return !printf("%lld/%lld\n",ans[x]/d,t/d);
}
int main()
{
int n=inn(),m=inn();
for(int i=1;i<=n;i++) init(i,inn());
for(int i=1;i<n;i++) link(inn(),inn());
while(m--)
{
int opt=inn(),x=inn(),y=inn();
if(opt==1) cut(x,y);
if(opt==2) link(x,y);
if(opt==3) update(x,y,inn());
if(opt==4) query(x,y);
}
return 0;
}