luogu P4292 [WC2010]重建计划

题面传送门
这个一眼分数规划然后转化成树上长度在\([L,R]\)之间的最长路径问题。
这个东西可以长链剖分解决,就是像重链剖分一样用线段树维护,然后轻儿子暴力查找和加入即可。
注意不要忘了一条链的情况。
时间复杂度\(O(nlognlogw)\)
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 100000
#define K 50
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,k,x,y,z,Up,Low,len[N+5],son[N+5],id[N+5],idea;db l,r,mid,W[N+5],F[N+5<<2],Ans,now;
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 void build(int l=1,int r=n,int now=1){F[now]=-1e18;if(l==r) return;int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);}
I void insert(int x,db y,int l=1,int r=n,int now=1){F[now]=max(F[now],y);if(l==r)return;int m=l+r>>1;x<=m?insert(x,y,l,m,now<<1):insert(x,y,m+1,r,now<<1|1);}
I db Query(int x,int y,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return F[now];int m=l+r>>1;db Ans1=-1e18,Ans2=-1e18;x<=m&&(Ans1=Query(x,y,l,m,now<<1));y>m&&(Ans2=Query(x,y,m+1,r,now<<1|1));return max(Ans1,Ans2);}
I void dfs1(int x,int last){yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs1(tmp.to,x),len[son[x]]<len[tmp.to]&&(son[x]=tmp.to));len[x]=len[son[x]]+1;}
I void dfs2(int x,int last){id[x]=++idea;if(!son[x]) return;dfs2(son[x],x);yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&tmp.to^son[x]&&(dfs2(tmp.to,x),0);}
I void Make(int x,int last){yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(W[tmp.to]=W[x]+tmp.w-mid,Make(tmp.to,x),0);}
I void dfs(int x,int last){
	yyy tmp;int i,j;insert(id[x],W[x]);if(!son[x]) return;dfs(son[x],x);for(int i=s.h[x];i;i=tmp.z){
		tmp=s.f[i];if(tmp.to==last||tmp.to==son[x])continue;dfs(tmp.to,x);for(j=max(1,Low-len[x]+1);j<=min(len[tmp.to],Up);j++) now=Query(id[tmp.to]+j-1,id[tmp.to]+j-1)+Query(id[x]+max(Low-j,0),id[x]+min(Up-j,len[x]-1)),Ans=max(Ans,now-2*W[x]);
		for(j=1;j<=len[tmp.to];j++) insert(id[x]+j,Query(id[tmp.to]+j-1,id[tmp.to]+j-1));
	}len[x]-1>=Low&&(now=Query(id[x]+Low,id[x]+min(Up,len[x]-1)),Ans=max(Ans,now-W[x]));
}
I int check(db mid){build();Ans=-1e18;Make(1,0);dfs(1,0);return Ans>=0;}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%d%d%d",&n,&Low,&Up);for(i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),s.add(x,y,z),s.add(y,x,z),r=max(r,z);dfs1(1,0);dfs2(1,0);l=0;r++;while(l+eps<r) mid=(l+r)/2,(check(mid)?l:r)=mid;printf("%.3lf\n",l);
}
上一篇:在PHP脚本中保护MySQL密码


下一篇:c# – MVC 3,用于用户注册过程的View Model.密码验证无法正常工作