bzoj3219 巡游(二分答案+点分治+单调队列)
2018-01-18 09:08
375 查看
求中位数最大的路径。我们二分答案,把>=mid的边都变成1,< mid的边都变成-1,如果有一条路径的权值和≥0,则中位数可以为mid。所以我们就是要去找一条权值和最大的路径。具体做法与bzoj1758相同。
我把leoly慢了8s啊,orz
我把leoly慢了8s啊,orz
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define ll long long #define inf 0x3f3f3f3f #define N 100010 #define pa pair<int,int> 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=x*10+ch-'0',ch=getchar(); return x*f; } int n,L,R,h ,num=0,rt,sz ,sumsz,f ,sonnum=0,mxr=0,ans=0,dep ,dis ,g ,tmp ; bool vis ;int mxdep,mid,fa ; struct edge{ int to,next,val; }data[N<<1]; struct Son{ int id,val; friend bool operator<(Son a,Son b){return sz[a.id]<sz[b.id];} }son ; void dfs1(int x){ sz[x]=1; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]||y==fa[x]) continue; fa[y]=x;dep[y]=dep[x]+1;dfs1(y);sz[x]+=sz[y]; } } void dfs2(int x){ f[x]=0; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]||y==fa[x]) continue; dfs2(y);f[x]=max(f[x],sz[y]); }f[x]=max(f[x],sumsz-sz[x]);if(f[x]<f[rt]) rt=x; } void dfs3(int x){ g[dep[x]]=max(g[dep[x]],dis[x]);mxdep=max(mxdep,dep[x]); for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(y==fa[x]||vis[y]) continue; dis[y]=dis[x]+(data[i].val>=mid?1:-1);dfs3(y); } } inline bool jud(int x){ tmp[0]=0;int mx=0;bool flag=0; for(int ii=1;ii<=sonnum;++ii){ int y=son[ii].id;mxdep=0;dis[y]=son[ii].val>=mid?1:-1;dfs3(y); deque<pa>q;int now=L-mxdep;if(now<0) now=0; for(int i=mxdep;i>=1;--i){ while(now<=mx&&now+i<=R){ while(!q.empty()&&tmp[now]>=q.back().first) q.pop_back(); q.push_back(make_pair(tmp[now],now));++now; }while(!q.empty()&&q.front().second+i<L) q.pop_front(); if(!q.empty()&&q.front().first+g[i]>=0){flag=1;break;} }for(int i=1;i<=mxdep;++i) tmp[i]=max(tmp[i],g[i]),g[i]=-inf;mx=max(mx,mxdep);if(flag) break; }for(int i=0;i<=mx;++i) tmp[i]=-inf; return flag; } inline void solve(int x){ vis[x]=1;fa[x]=0;dep[x]=0;dfs1(x); if(sz[x]<L) return;sonnum=0; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]) continue; son[++sonnum].id=y;son[sonnum].val=data[i].val; }sort(son+1,son+sonnum+1); int l=ans,r=mxr; while(l<=r){ mid=l+r>>1; if(jud(x)) ans=mid,l=mid+1; else r=mid-1; }for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]) continue; rt=0;sumsz=sz[y];dfs2(y);solve(rt); } } int main(){ // freopen("a.in","r",stdin); n=read();L=read();R=read();f[0]=n+1; for(int i=1;i<n;++i){ int x=read(),y=read(),val=read();mxr=max(mxr,val); data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val; data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=val; }for(int i=1;i<=n;++i) g[i]=tmp[i]=-inf; dfs1(1);rt=0;sumsz=n;dfs2(1);solve(rt); if(!ans) puts("-1"); else printf("%d\n",ans); return 0; }
相关文章推荐
- bzoj 3219: 巡游 (点分治+单调队列+二分)
- 【bzoj1758】[Wc2010]重建计划 二分答案+单调队列+点分治
- BZOJ1758 [Wc2010]重建计划(二分答案+点分治+单调队列)
- 【BZOJ】【P1758】【Wc2010】【重建计划】【题解】【点分治+二分+单调队列】
- 巡游tour {二分+树分治+单调队列}
- BZOJ_P3048 [Usaco2013 Jan]Cow Lineup(二分答案+树状数组/单调队列)
- BZOJ 3316: JC loves Mkk|单调队列|二分答案
- [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案
- 【bzoj3316】【JC loves MKK】【单调队列+二分答案】
- 【bzoj3316】JC loves Mkk 二分答案+单调队列
- bzoj 2096: [Poi2010]Pilots (二分答案+单调队列)
- BZOJ 1758 Wc2010 重建计划 树的点分治+二分+单调队列
- wc2010 bzoj1758(点分治+二分+单调队列) TLE
- bzoj 4476: [Jsoi2015]送礼物 二分答案+单调队列
- 【bzoj3316】 JC loves Mkk 单调队列+二分答案
- BZOJ 3316 JC loves Mkk 二分答案+单调队列
- [二分答案 单调队列] BZOJ 3316 JC loves Mkk
- BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP+单调队列
- BZOJ1758【点分治】【二分】【单调队列】
- 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)