1758: [Wc2010]重建计划(TLE)
2017-04-25 16:55
190 查看
链接
http://www.lydsy.com/JudgeOnline/problem.php?id=1758题解?
首先说明这道题我没过。那为啥要写题解?
因为我确实写的正解啊。
不就是先二分答案,然后点分治,然后单调队列,还得按子树深度从小到大吗。
然后我就T了啊。
不就是扫把图吗,我本地也很快啊。
加数据的,你过来我和你说个事:我去年买了个表。
这个题啊,亦可赛艇。这个加数据人啊,更可赛艇。
算了算了,自己渣怪不了别人。
代码(没过)
//二分+点分治+单调队列 #include <cstdio> #include <algorithm> #include <ctime> #define maxn 100010 #define eps 1e-8 #define inf 1e100 #define ll long long #define forp for(int p=head[pos];p;p=nex[p])if(to[p]^pre and !grey[to[p]]) using namespace std; int N, head[maxn], to[maxn<<1], nex[maxn<<1], tot, list[maxn], deep[maxn], G, size[maxn], ndtot, L, R, q[maxn], tmp[maxn], maxdeep[maxn], zs[maxn], up, cnt, tab[maxn], tong[maxn]; ll sumG, t; double w[maxn<<1], dist[maxn], mid, ans, temp[maxn]; bool grey[maxn], flag; inline void adde(int a, int b, double v) {to[++tot]=b;w[tot]=v;nex[tot]=head[a];head[a]=tot;} inline int read(int x=0) { char c=getchar(); while(c<48 or c>57)c=getchar(); while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar(); return x; } void init() { int a, b, v, i; N=read(), L=read(), R=read(); for(i=1;i<N;i++) a=read(), b=read(), v=read(), adde(a,b,v),adde(b,a,v),up=max(up,v); } int dfs(int pos, int pre) { maxdeep[pos]=deep[pos]; list[++*list]=pos; size[pos]=1; forp dist[to[p]]=dist[pos]+w[p], deep[to[p]]=deep[pos]+1, size[pos]+=dfs(to[p],pos), maxdeep[pos]=max(maxdeep[pos],maxdeep[to[p]]); return size[pos]; } void findG(int pos, int pre, ll sum) { if(sum<sumG)G=pos, sumG=sum; forp findG(to[p],pos,sum+*size-(size[to[p]]<<1)); } inline int zhuang(int *a) { int i, lim=0; for(i=1;i<=*a;i++)lim=max(lim,deep[a[i]]); for(i=0;i<=lim;i++)tong[i]=0;dist[0]=-inf; for(i=1;i<=*a;i++)if(dist[a[i]]>dist[tong[deep[a[i]]]])tong[deep[a[i]]]=a[i]; return lim; } inline bool gao() { int a, b, l=1, r=1, x, i, p=1, lim=0; *q=0; lim=zhuang(tmp); for(i=lim,*tmp=0;i>=0;i--)if(tong[i])tmp[++*tmp]=tong[i]; lim=zhuang(list); for(i=0,*list=0;i<=lim;i++)if(tong[i])list[++*list]=tong[i]; for(i=1;i<=*list;i++) { a=max(0,L-deep[list[i]]), b=max(0,R-deep[list[i]]); while(deep[tmp[p]]>=a and p<=*tmp) { while(l<r and dist[tmp[p]]>dist[q[r-1]])r--; q[r++]=tmp[p++]; } while(l<r and deep[q[l]]>b)l++; if(l<r and dist[q[l]]+dist[list[i]]>-eps)return true; } for(i=1;i<=*list;i++)tmp[++*tmp]=list[i]; return false; } inline bool cmp(int a, int b){return maxdeep[a]<maxdeep[b];} inline void solve(int pos) { int i, j; double l, r; *list=0, deep[pos]=0, *size=dfs(pos,-1); for(sumG=0,i=1;i<=*list;i++)sumG+=deep[list[i]]; findG(G=pos,-1,sumG); grey[G]=1; *list=0, dist[G]=0, deep[G]=0, dfs(G,-1); for(i=1;i<=*list;i++)temp[list[i]]=dist[list[i]]; for(i=1;i<=*list;i++)if(temp[list[i]]>ans-eps)break; *zs=0; for(int p=head[G];p;p=nex[p])if(!grey[to[p]])zs[++*zs]=to[p]; sort(zs+1,zs+*zs+1,cmp); for(l=ans,r=up;r-l>1e-4;) { mid=(l+r)/2.0; tmp[*tmp=1]=G; for(i=1;i<=*zs;i++) { *list=0, dfs(zs[i],G); for(j=1;j<=*tmp;j++)dist[tmp[j]]=temp[tmp[j]]-deep[tmp[j]]*mid; for(j=1;j<=*list;j++)dist[list[j]]=temp[list[j]]-deep[list[j]]*mid; if(gao()){l=mid;break;} } if(i>*zs)r=mid; } ans=max(ans,l); for(int p=head[G];p;p=nex[p])if(!grey[to[p]])solve(to[p]); } int main() { init(); int i; double l, r; solve(1); printf("%.3lf",ans); return 0; }
相关文章推荐
- bzoj1758 [Wc2010]重建计划(二分答案+点分治+单调栈)
- bzoj 1758 [Wc2010]重建计划 01分数规划 点分治 单调队列
- Bzoj1758: [Wc2010]重建计划
- bzoj1758 [Wc2010]重建计划(点分治+01分数规划)
- 1758: [Wc2010]重建计划
- Bzoj1758: [Wc2010]重建计划
- bzoj 1758: [Wc2010]重建计划 长链剖分+线段树
- bzoj1758 [Wc2010]重建计划
- 【BZOJ1758】【Wc2010】重建计划 树的点分治 二分
- bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race
- bzoj1758 [Wc2010]重建计划
- 【BZOJ 1758】 [Wc2010]重建计划
- 1758: [Wc2010]重建计划
- 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)
- 树的点分治 bzoj1758【WC2010】重建计划
- bzoj 1758: [Wc2010]重建计划 (01分数规划+点分治)
- BZOJ 1758 【WC2010】 重建计划
- [bzoj1758][Wc2010]重建计划
- 【bzoj1758】[Wc2010]重建计划 二分答案+单调队列+点分治
- [BZOJ]1758: [Wc2010]重建计划