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黄学长!!!
代码:
View Code
题解:终于了结了好久以来的一个大坑。。。
原来想的是怎么能点分治并且用堆的写法?今天发现真的可以这样做!!!
我们在点分的时候直接把每个状态保存下来(时间允许,所以空间一定允许)。然后对每个区间保存一个区间[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
相关文章推荐
- [BZOJ3784]树上的路径(点分治+dfs序+st表+堆)
- [可持久化可并堆 || ST表 点分治] BZOJ 3784 树上的路径
- bzoj3784 树上的路径
- [bzoj3784]树上的路径
- BZOJ 3784|树上的路径|点分治|堆|RMQ
- 【BZOJ-3784】树上的路径 点分治 + ST + 堆
- 【BZOJ3784】树上的路径 点分治序+ST表
- [bzoj3784][点分治]树上的路径
- bzoj 3784: 树上的路径 点分治+RMQ+堆
- bzoj 3784: 树上的路径 堆维护第k大
- [BZOJ3784]树上的路径 点分治序+ST表
- BZOJ3784 : 树上的路径
- bzoj 3784: 树上的路径【点分治+st表+堆】
- [BZOJ 3784][树上的路径][点分治+堆]
- 树上的路径 BZOJ 3784
- 【bzoj3784】【树上的路径】【点分治+堆+st表】
- bzoj 3784: 树上的路径 (ST表+优先队列+点分治)
- 【bzoj3784】树上的路径
- bzoj 3784: 树上的路径
- 【BZOJ 2588】Count on a tree 【树上路径第K大】【LCA+主席树】