ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ #3784. 树上的路径

2021-08-17 18:01:42  阅读:168  来源: 互联网

标签:3784 int BZOJ 路径 long Ans now void define


题面传送门
首先显然有一个三只log的做法,就是先二分,然后点分找大于这个值的路径,直接爆炸。
考虑有什么更优的方法,我们将点分治的顺序跑出来,然后发现一个点计算答案的区间一定是一段区间。
然后我们像超级钢琴那样就好了。
区间最大值的话如果是线段树是\(O(n+m)logn\),st表是\(O(nlog^2n+mlogn)\),关键这两个跑得一样快。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 200000
#define K 20
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Pc(x) putchar(x) 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,k,d[N+5<<5],siz[N+5],Maxn[N+5],vis[N+5],F[N+5],dfn[N+5<<5],dh,l[N+5<<5],r[N+5<<5],root,G[N+5<<7],pus,p,x,y,z;
struct yyy{int to,w,z;};
struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}}s;
I int Getsiz(int x,int last){int Ans=1;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&!vis[tmp.to]&&(Ans+=Getsiz(tmp.to,x));return Ans;}
I void dfs1(int x,int last,int sum){F[x]=1;Maxn[x]=0;yyy tmp;for(int i=s.h[x];i;i=tmp.z)tmp=s.f[i],tmp.to^last&&!vis[tmp.to]&&(dfs1(tmp.to,x,sum),F[x]+=F[tmp.to],Maxn[x]=max(Maxn[x],F[tmp.to]));Maxn[x]=max(Maxn[x],sum-F[x]);Maxn[x]<=sum/2&&(root=x);}
I void dfs2(int x,int last,int ls,int rs){int now;dfn[now=++dh]=x;l[dh]=ls;r[dh]=rs;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],!vis[tmp.to]&&tmp.to^last&&(d[dh+1]=d[now]+tmp.w,dfs2(tmp.to,x,ls,rs),0);}
I void dfs(int x){
	yyy tmp;root=x;dfs1(x,0,Getsiz(x,0));x=root;vis[x]=1;dfn[++dh]=x;l[dh]=r[dh]=dh;int i,lastdh=dh;for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],!vis[tmp.to]&&(d[dh+1]=tmp.w,dfs2(tmp.to,x,lastdh,dh),0);for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],!vis[tmp.to]&&(dfs(tmp.to),0);
}
struct Ques{int w,id,l,r,p;bool operator <(const Ques &B)const{return w<B.w;};}now;priority_queue<Ques> Q;I int Up(int x,int y){return d[x]>d[y]?x:y;}
I void build(int l=1,int r=dh,int now=1){if(l==r) return (void)(G[now]=l);int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);G[now]=Up(G[now<<1],G[now<<1|1]);}
I int Query(int x,int y,int l=1,int r=dh,int now=1){if(x<=l&&r<=y) return G[now];int m=l+r>>1,Ans=0;x<=m&&(Ans=Up(Ans,Query(x,y,l,m,now<<1)));y>m&&(Ans=Up(Ans,Query(x,y,m+1,r,now<<1|1)));return Ans;}
int main(){
//	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i;scanf("%d%d",&n,&m);for(i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),s.add(x,y,z),s.add(y,x,z);dfs(1);build();for(i=1;i<=dh;i++) pus=Query(l[i],r[i]),Q.push((Ques){d[pus]+d[i],i,l[i],r[i],pus});
	while(m--){now=Q.top();Q.pop();printf("%d\n",now.w);now.p^now.l&&(pus=Query(now.l,now.p-1),Q.push((Ques){d[pus]+d[now.id],now.id,now.l,now.p-1,pus}),0);now.p^now.r&&(pus=Query(now.p+1,now.r),Q.push((Ques){d[pus]+d[now.id],now.id,now.p+1,now.r,pus}),0);}
}

标签:3784,int,BZOJ,路径,long,Ans,now,void,define
来源: https://www.cnblogs.com/275307894a/p/15153498.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有