BZOJ 1758
mengbing。。。。。
大家都说这是一道卡常题 、名不虚传、233333
树分治 再加上迭代答案 而不是二分 就可以过了
迭代的次数 平均下来 大概就只有 2.8次的样子
需要单调队列优化更新答案的过程
BZOJ 1758
1 #include <bits/stdc++.h> 2 #define N 100010 3 #define inf 1e10 4 using namespace std; 5 inline int read() 6 { 7 int x=0,f=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 10 return x*f; 11 } 12 struct edge 13 { 14 int v,next,w; 15 }vs[N<<1]; 16 int n,L,R,q[N],vis[N],sum,Rtt; 17 int st[N],ee,Rt,size[N],tp[N],dep[N]; 18 int stk[N],top,fa[N],mxd; 19 double prestans=0.0,ans,vopt[N],,f[N]; 20 vector <int> Gp[N]; 21 inline void addedge(int u,int v,int w) 22 { 23 vs[++ee].v=v;vs[ee].w=w; 24 vs[ee].next=st[u];st[u]=ee; 25 } 26 void dfs1(int rt,int pr) 27 { 28 size[rt]=1; 29 for(int i=st[rt];i;i=vs[i].next) 30 { 31 if(vs[i].v==pr||vis[vs[i].v]) continue; 32 dfs1(vs[i].v,rt); 33 size[rt]+=size[vs[i].v]; 34 } 35 } 36 void dfs2(int rt,int pr) 37 { 38 tp[rt]=0; 39 for(int i=st[rt];i;i=vs[i].next) 40 { 41 if(vs[i].v==pr||vis[vs[i].v]) continue; 42 dfs2(vs[i].v,rt); 43 tp[rt]=max(tp[rt],size[vs[i].v]); 44 } 45 tp[rt]=max(tp[rt],sum-size[rt]); 46 if(tp[rt]<tp[Rtt]) Rtt=rt; 47 } 48 void predeal(int rt) 49 { 50 vis[rt]=1; 51 for(int i=st[rt];i;i=vs[i].next) 52 { 53 if(vis[vs[i].v]) continue; 54 Rtt=0; dfs1(vs[i].v,rt); 55 sum=size[vs[i].v]; 56 dfs2(vs[i].v,rt); 57 Gp[rt].push_back(Rtt); 58 predeal(Rtt); 59 } 60 } 61 void getans(int rt,int val) 62 { 63 stk[top=1]=rt; fa[1]=0; f[1]=val; dep[1]=1; 64 for(int i=1;i<=top;i++) 65 { 66 for(int j=st[stk[i]];j;j=vs[j].next) 67 { 68 if(vis[vs[j].v]||vs[j].v==fa[i]) continue; 69 stk[++top]=vs[j].v; dep[top]=dep[i]+1; 70 fa[top]=stk[i]; f[top]=f[i]+vs[j].w; 71 } 72 } 73 int l=1,r=0,pre=mxd; 74 for(int i=1,j;i<=top;i=j) 75 { 76 double mx=-inf; 77 for(j=i;dep[j]==dep[i]&&j<=top;j++) 78 mx=max(mx,f[j]); 79 while(pre>=0&&pre>=L-dep[i]) 80 { 81 while(vopt[q[r]]<vopt[pre]&&r>=l) r--; 82 q[++r]=pre; pre--; 83 } 84 85 while(q[l]+dep[i]>R&&l<=r) l++; 86 if(l<=r) ans=max(ans,(vopt[q[l]]+mx+prestans*q[l])/(q[l]+dep[i])); 87 } 88 for(int i=1;i<=top;i++) 89 vopt[dep[i]]=max(vopt[dep[i]],f[i]-dep[i]*prestans); 90 mxd=max(mxd,dep[top]); 91 } 92 void solve(int rt) 93 { 94 vis[rt]=1; mxd=0; vopt[0]=0; 95 for(int i=st[rt];i;i=vs[i].next) 96 { 97 if(vis[vs[i].v]) continue; 98 getans(vs[i].v,vs[i].w); 99 } 100 for(int i=0;i<=mxd;i++) vopt[i]=-inf; 101 for(unsigned i=0;i<Gp[rt].size();i++) 102 solve(Gp[rt][i]); 103 } 104 double check() 105 { 106 memset(vis,0,sizeof vis); 107 ans=-inf; 108 solve(Rt); 109 return ans; 110 } 111 int main() 112 { 113 //freopen("read.in","r",stdin); 114 n=read();L=read();R=read(); 115 for(int i=1;i<n;i++) 116 { 117 int x=read(),y=read(),w=read(); 118 addedge(x,y,w);addedge(y,x,w); 119 } 120 dfs1(1,0); 121 Rtt=0; tp[0]=n+1; sum=n; 122 dfs2(1,0); 123 Rt=Rtt; predeal(Rt); 124 for(int i=1;i<=n;i++) vopt[i]=-inf; 125 for(int i=1;i<=3;i++) 126 prestans=check(); 127 printf("%.3lf",prestans); 128 return 0; 129 }
↓↓↓↓ dmk ↓↓↓↓
1 #include <bits/stdc++.h> 2 #define N 100000 3 using namespace std; 4 5 struct edge 6 { 7 int u,v,next,w; 8 }vs[N<<1]; 9 int st[N+100],ee,dep[N+100],mx1,mx2; 10 inline void addedge(int u,int v,int w) 11 { 12 vs[++ee].v=v;vs[ee].next=st[u]; 13 vs[ee].u=u;vs[ee].w=w;st[u]=ee; 14 } 15 int main() 16 { 17 srand(time(0)); 18 freopen("read.in","w",stdout); 19 printf("%d\n",N); 20 for(int i=2;i<=N;i++) 21 { 22 int u=rand()*rand()%(i-1)+1; 23 addedge(u,i,rand()*rand()%1000000); 24 dep[i]=dep[u]+1; 25 if(dep[i]>=mx1) mx2=mx1,mx1=dep[i]; 26 else if(dep[i]>mx2) mx2=dep[i]; 27 } 28 int L=rand()*rand()%(mx1+mx2)+1,R=rand()*rand()%(mx1+mx2)+1; 29 if(L>R) swap(L,R); 30 /* sort(dep+1,dep+1+N); 31 for(int i=1;i<=N;i++) 32 printf("%d ",dep[i]); printf("\n"); */ 33 printf("%d %d\n",L,R); 34 for(int i=1;i<=N;i++) 35 printf("%d %d %d\n",vs[i].u,vs[i].v,vs[i].w); 36 return 0; 37 }
好好讲道理 应该求出直径 所以这个dmk 有问题2333 但总体还是能拍得出来 逃