bzoj3784: 树上的路径
题解:
点分治序列+超级钢琴那题
搞出点分治序列
那么每个点能构成路径的就是连续的一段
上次是用线段树维护的。。这次就用st表了
代码:
#include <bits/stdc++.h> using namespace std; #define IL inline #define rint register int #define me(x) memset(x,0,sizeof(x)) #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define mid ((h+t)/2) char ss[1<<24],*A=ss,*B=ss; char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T> void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48; while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } const int INF=1e9; const int N=6e5+10; const int N2=1e8; struct re{ int a,b,c; }a[N]; struct re1{ int a,b,c,d,e; }; struct cmp{ bool operator() (re1 x,re1 y) { return(x.a<y.a); } }; priority_queue<re1,vector<re1>,cmp> Q; int head[N],l,n,m,rt,son[N],f[N],cnt,sum,d[N]; int s[N2],t[N2],p[N2]; bool vis[N]; IL void arr(int x,int y,int z) { a[++l].a=head[x]; a[l].b=y; a[l].c=z; head[x]=l; } void gr(int x,int fa) { son[x]=1;f[x]=0; int u=head[x]; while (u) { int v=a[u].b; if (vis[v]&&v!=fa) { gr(v,x); son[x]+=son[v]; f[x]=max(f[x],son[v]); } u=a[u].a; } f[x]=max(f[x],sum-son[x]); if(f[x]<f[rt]) rt=x; } void gd(int x,int fa,int bg,int ed,int z) { int u=head[x]; while (u) { int v=a[u].b; if (vis[v]&&v!=fa) { d[v]=d[x]+a[u].c; p[++cnt]=d[v]; if (x==z) { s[cnt]=bg; t[cnt]=cnt-1; gd(v,x,bg,cnt-1,z); } else { s[cnt]=bg; t[cnt]=ed; gd(v,x,bg,ed,z); } } u=a[u].a; } } int num; void solve(int x,int y) { int u=head[x]; vis[x]=0; int bg=cnt+1; d[x]=0; gd(x,0,bg,0,x); p[++cnt]=0; s[cnt]=bg; t[cnt]=cnt-1; while (u) { int v=a[u].b; if (vis[v]) { rt=0; sum=son[v]; gr(v,x); solve(rt,y+1); } u=a[u].a; } } int bz[20][N],bz2[20][N]; IL re query(int x,int y) { int z=log2(y-x+1); if (bz[z][x]>bz[z][y-(1<<z)+1]) return((re){bz2[z][x],bz[z][x]}); else return((re){bz2[z][y-(1<<z)+1],bz[z][y-(1<<z)+1]}); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); read(n); read(m); rep(i,1,n-1) { int x,y,z; read(x); read(y); read(z); arr(x,y,z); arr(y,x,z); } memset(vis,1,sizeof(vis)); f[0]=INF; sum=n; gr(1,0); solve(rt,0); rep(i,1,cnt) bz[0][i]=p[i],bz2[0][i]=i; rep(i,1,16) rep(j,1,cnt) if (bz[i-1][j]>bz[i-1][j+(1<<(i-1))]) bz[i][j]=bz[i-1][j],bz2[i][j]=bz2[i-1][j]; else bz[i][j]=bz[i-1][j+(1<<(i-1))],bz2[i][j]=bz2[i-1][j+(1<<(i-1))]; rep(i,1,cnt) { if (s[i]<=t[i]) { re xx=query(s[i],t[i]); int x=xx.a,y=xx.b; Q.push((re1){p[i]+y,i,s[i],t[i],x}); } } int ans; rep(i,1,m) { re1 xx=Q.top(); Q.pop(); ans=xx.a; int j=xx.b; if (xx.c<xx.e) { re z=query(xx.c,xx.e-1); int x=z.a,y=z.b; Q.push((re1){p[j]+y,j,xx.c,xx.e-1,x}); } if (xx.e<xx.d) { re z=query(xx.e+1,xx.d); int x=z.a,y=z.b; Q.push((re1){p[j]+y,j,xx.e+1,xx.d,x}); } cout<<ans<<endl; } return 0; }