您的位置:首页 > 其它

BZOJ3784: 树上的路径

2015-03-25 00:10 330 查看
题目: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黄学长!!!

代码:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 50000+5
#define maxm 1000000+5
#define eps 1e-10
#define ll long long
#define ull unsigned long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
#define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
#define mod 1000000007
#define lch k<<1,l,mid
#define rch k<<1|1,mid+1,r
#define sqr(x) (x)*(x)
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
int n,m,l,r,sum,tot,rt,s[maxn],ss[maxn],head[maxn];
bool del[maxn];
int f[maxm][2],g[maxm],mx[maxm][21];
struct edge{int go,next,w;}e[2*maxn];
struct rec
{
int l,r,x,y;
};
bool operator <(rec a,rec b){return g[a.x]+g[a.y]<g[b.x]+g[b.y];}
priority_queue<rec>q;
inline void add(int x,int y,int w)
{
e[++tot]=(edge){y,head[x],w};head[x]=tot;
e[++tot]=(edge){x,head[y],w};head[y]=tot;
}
inline void getrt(int x,int fa)
{
s[x]=1;ss[x]=0;
for4(i,x)if(!del[y]&&y!=fa)
{
getrt(y,x);
s[x]+=s[y];
ss[x]=max(ss[x],s[y]);
}
ss[x]=max(ss[x],sum-s[x]);
if(ss[x]<ss[rt])rt=x;
}
inline void get(int x,int fa,int w)
{
g[++tot]=w;f[tot][0]=l;f[tot][1]=r;
for4(i,x)if(!del[y]&&y!=fa)get(y,x,w+e[i].w);
}
inline void solve(int x)
{
del[x]=1;
l=r=++tot;
for4(i,x)if(!del[y])get(y,x,e[i].w),r=tot;
for4(i,x)if(!del[y]){sum=s[y];rt=0;getrt(y,x);solve(rt);}
}
inline int query(int x,int y)
{
int t=log2(y-x+1),t1=mx[x][t],t2=mx[y-(1<<t)+1][t];
return g[t1]>g[t2]?t1:t2;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();
for1(i,n-1){int x=read(),y=read();add(x,y,read());}
tot=0;sum=n;
ss[rt=0]=inf;
getrt(1,0);
solve(rt);
for1(i,tot)mx[i][0]=i;
for1(i,20)
for1(j,tot-(1<<i)+1)
{
int t1=mx[j][i-1],t2=mx[j+(1<<(i-1))][i-1];
mx[j][i]=g[t1]>g[t2]?t1:t2;
}
for1(i,tot)q.push((rec){f[i][0],f[i][1],i,query(f[i][0],f[i][1])});
while(m--)
{
rec t=q.top();q.pop();
printf("%d\n",g[t.x]+g[t.y]);
if(t.y+1<=t.r)q.push((rec){t.y+1,t.r,t.x,query(t.y+1,t.r)});
if(t.y-1>=t.l)q.push((rec){t.l,t.y-1,t.x,query(t.l,t.y-1)});
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: