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; 
}

 

 

 

posted @ 2018-07-12 23:35  尹吴潇  阅读(47)  评论(0编辑  收藏