BZOJ3784: 树上的路径

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3784

题解:终于了结了好久以来的一个大坑。。。

        原来想的是怎么能点分治并且用堆的写法?今天发现真的可以这样做!!!

        我们在点分的时候直接把每个状态保存下来(时间允许,所以空间一定允许)。然后对每个区间保存一个区间[l,r]表示他可以从与[l,r]的节点构成一条完整的路径。

        这样在堆里把每个元素x放入,存为一个四元组(l,r,x,y)表示是x可以与[l,r]的节点构成路径,这其中最长的是y。然后每次取出最大之后就可以放入(l,y-1,x,max(l,y-1))和(y+1,r,x,max(y+1,r))

        最大值用st表预处理一下即可。真是Orz黄学长!!!

代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<vector>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<string>
 12 #define inf 1000000000
 13 #define maxn 50000+5
 14 #define maxm 1000000+5
 15 #define eps 1e-10
 16 #define ll long long
 17 #define ull unsigned long long
 18 #define pa pair<int,int>
 19 #define for0(i,n) for(int i=0;i<=(n);i++)
 20 #define for1(i,n) for(int i=1;i<=(n);i++)
 21 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 22 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 23 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 24 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
 25 #define mod 1000000007
 26 #define lch k<<1,l,mid
 27 #define rch k<<1|1,mid+1,r
 28 #define sqr(x) (x)*(x)
 29 using namespace std;
 30 inline int read()
 31 {
 32     int x=0,f=1;char ch=getchar();
 33     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 34     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 35     return x*f;
 36 }
 37 int n,m,l,r,sum,tot,rt,s[maxn],ss[maxn],head[maxn];
 38 bool del[maxn];
 39 int f[maxm][2],g[maxm],mx[maxm][21];
 40 struct edge{int go,next,w;}e[2*maxn];
 41 struct rec
 42 {
 43     int l,r,x,y;
 44 };
 45 bool operator <(rec a,rec b){return g[a.x]+g[a.y]<g[b.x]+g[b.y];}
 46 priority_queue<rec>q;
 47 inline void add(int x,int y,int w)
 48 {
 49     e[++tot]=(edge){y,head[x],w};head[x]=tot;
 50     e[++tot]=(edge){x,head[y],w};head[y]=tot;
 51 }
 52 inline void getrt(int x,int fa)
 53 {
 54    s[x]=1;ss[x]=0;
 55    for4(i,x)if(!del[y]&&y!=fa)
 56    {
 57          getrt(y,x);
 58          s[x]+=s[y];
 59          ss[x]=max(ss[x],s[y]);
 60    }
 61    ss[x]=max(ss[x],sum-s[x]);
 62    if(ss[x]<ss[rt])rt=x;
 63 }
 64 inline void get(int x,int fa,int w)
 65 {
 66    g[++tot]=w;f[tot][0]=l;f[tot][1]=r;
 67    for4(i,x)if(!del[y]&&y!=fa)get(y,x,w+e[i].w);
 68 }
 69 inline void solve(int x)
 70 {
 71    del[x]=1;
 72    l=r=++tot;
 73    for4(i,x)if(!del[y])get(y,x,e[i].w),r=tot;
 74    for4(i,x)if(!del[y]){sum=s[y];rt=0;getrt(y,x);solve(rt);}
 75 }
 76 inline int query(int x,int y)
 77 {
 78    int t=log2(y-x+1),t1=mx[x][t],t2=mx[y-(1<<t)+1][t];
 79    return g[t1]>g[t2]?t1:t2;
 80 }
 81 int main()
 82 {
 83    freopen("input.txt","r",stdin);
 84    freopen("output.txt","w",stdout);
 85    n=read();m=read();
 86    for1(i,n-1){int x=read(),y=read();add(x,y,read());}
 87    tot=0;sum=n;
 88    ss[rt=0]=inf;
 89    getrt(1,0);
 90    solve(rt);
 91    for1(i,tot)mx[i][0]=i;
 92    for1(i,20)
 93     for1(j,tot-(1<<i)+1)
 94      {
 95          int t1=mx[j][i-1],t2=mx[j+(1<<(i-1))][i-1];
 96          mx[j][i]=g[t1]>g[t2]?t1:t2;
 97      }
 98    for1(i,tot)q.push((rec){f[i][0],f[i][1],i,query(f[i][0],f[i][1])});
 99    while(m--)
100    {
101         rec t=q.top();q.pop();
102         printf("%d\n",g[t.x]+g[t.y]);
103       if(t.y+1<=t.r)q.push((rec){t.y+1,t.r,t.x,query(t.y+1,t.r)});
104       if(t.y-1>=t.l)q.push((rec){t.l,t.y-1,t.x,query(t.l,t.y-1)});
105    }
106    return 0;
107 }
View Code

 

posted @ 2015-03-25 00:10  ZYF-ZYF  Views(793)  Comments(0Edit  收藏  举报