WC 2010 rebuild 重建计划
来源:互联网 发布:matlab等差数组 编辑:程序博客网 时间:2024/05/21 17:41
题目描述就不说了。要题目的请往百度NOI吧。
经典的树的分治,首先,对于答案是分数形式的基本上要使用二分答案,这不是胡扯,详情请见胡伯涛的论文。
那么对于这个题,由于不好估计边分治复杂度(其实边分治是可以过的,好像比点分治要快),对于答案,化成如下形式sigma{e}-ans*s=0,对于一个可行的ans设为val,必然满足sigma{e}-val*s>=0,所以二分。
点分治时,将每个节点到根的路径的权值计算出来,同时记录走过了多少条边。然后按照在每个子树中按照路径走过的边的数目排序,二分答案后验证,合并子树时,第一颗子树在一个数组list中按序保存走过s条边的路径权值最大值,以后的子树中枚举每条路径,利用单调性每次从list中加入一个值用单调队列维护路径的合法性和最优性,在做完一颗子树后这个子树保存的路径与list数组保存的信息合并,作为下一次list使用。
复杂度分析:点分治O(nlogn),每个节点被访问logn+1次,排序O(nlogn)为上限,二分答案验证为O(nlogans),一共做logn次,所以为O(nlognlogans)
Code:(注:不要作为对拍程序,貌似实现有bug)
#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>struct element{ int key; double val;} que[100005],lis[2][100005];const double oo=10000000;const element ori={0,0};int vis[100005],sta[100005],next[200005],link[200005],head[100005],sum[100005],f[100005],l[100005],r[100005],dis[100005],a[100005],b[100005],count[100005],w[200005],pre[200005],tot[2],hea=0,tai=0;bool flag[100005];int time=0,top=0,tail=0,now=0,e=1,up=0,dn=0,n=0;double ans=0,limitup=0,limitdn=0,mid=0;inline void add(int u,int v,int tmpw){ next[++e]=head[u]; head[u]=e; link[e]=v; w[e]=tmpw; pre[next[e]]=e; next[++e]=head[v]; head[v]=e; link[e]=u; w[e]=tmpw; pre[next[e]]=e;}inline void update(double &a,double b){ if (a<b) a=b;}inline int cal(int s){ ++time; f[s]=0; top=0; vis[s]=time; sta[tail=1]=s; int ne=0,y=0,x=0,i=0; while (top<tail) { x=sta[++top]; for (ne=head[x],y=link[ne];ne;ne=next[ne],y=link[ne])if (vis[y]!=time) { vis[y]=time; sta[++tail]=y; f[y]=x; } sum[x]=0; flag[x]=1; } if (tail==1) return s; for (i=tail,x=sta[i];i>=1;i--,x=sta[i]) { sum[x]++; sum[f[x]]+=sum[x]; if (sum[x]<=tail/2) flag[x]=0; if (sum[x]>tail/2) flag[f[x]]=0; if (flag[x]) return x; }}void print(int s){ for (;s;s=f[s]) printf("%d ",s); printf("\n");}void dfs(int s){ vis[s]=time; int ne=0,x=0; l[s]=r[s]=++now; a[now]=dis[s]; b[now]=count[s]; for (ne=head[s],x=link[ne];ne;ne=next[ne],x=link[ne]) if (vis[x]!=time) {f[x]=s;dis[x]=dis[s]+w[ne];count[x]=count[s]+1;if (dn<=count[x] && count[x]<=up) update(ans,(double)(dis[x])/count[x]);dfs(x);r[s]=r[x]; }}inline void swap(int &a,int &b){ int tmp=a; a=b; b=tmp;}inline void qs(int h,int g){ int l=h,k=g,mid=b[(l+k)/2]; while (l<=k) { while (b[l]<mid) l++; while (b[k]>mid) k--; if (l<=k){ swap(b[l],b[k]); swap(a[l],a[k]); l++; k--;} } if (l<g) qs(l,g); if (h<k) qs(h,k);}inline bool com(int st){ return (dn<=st && st<=up);}bool check(double mid,int s){ int ne=head[s],x=link[ne],i=0,j=0,now=0,oth=1; double tmpw=0; tot[0]=tot[1]=hea=tai=0; for (i=l[x];i<=r[x];i++) { if (b[i]==b[i-1]) update(lis[now][tot[now]].val,a[i]-b[i]*mid); else{ lis[now][++tot[now]].val=a[i]-b[i]*mid; lis[now][tot[now]].key=b[i];} } for (ne=next[ne],x=link[ne];ne;ne=next[ne],x=link[ne]) { hea=tai=0; j=tot[now]; for (i=l[x];i<=r[x];i++){ tmpw=a[i]-b[i]*mid; for (;!com(que[hea].key+b[i]) && hea<=tai;hea++); for (;lis[now][j].key+b[i]>up && j>0;j--); for (;com(lis[now][j].key+b[i]) && j>0;j--) { for (;lis[now][j].val>que[tai].val && hea<=tai;tai--); que[++tai]=lis[now][j]; } if (hea<=tai && que[hea].val+tmpw>-(1e-5) && com(que[hea].key+b[i])) return 1;} oth=now; now=1-now; tot[now]=0; i=l[x];j=1; lis[oth][tot[oth]+1].key=n+1; while (i<=r[x] || j<=tot[oth]){ for (;i<=r[x] && lis[now][tot[now]].key==b[i];i++) update(lis[now][tot[now]].val,a[i]-b[i]*mid); for (;j<=tot[oth] && lis[now][tot[now]].key==lis[oth][j].key;j++) update(lis[now][tot[now]].val,lis[oth][j].val); if (i<=r[x]) if (b[i]<=lis[oth][j].key) lis[now][++tot[now]].key=b[i],lis[now][tot[now]].val=a[i]-b[i]*mid,i++; else lis[now][++tot[now]]=lis[oth][j],j++; else if (j<=tot[oth]) lis[now][++tot[now]]=lis[oth][j],j++;} } return 0;}void getans(int s){ if (tail<dn) return; ++time; now=0; dis[s]=0;count[s]=0; f[s]=0; limitdn=0; dfs(s); limitup=1e6; int ne=0,x=0,me=0; for (ne=head[s],x=link[ne];ne;ne=next[ne],x=link[ne]) qs(l[x],r[x]); while (limitdn+1e-5<limitup) { mid=(limitup+limitdn)/2; if (check(mid,s))limitdn=mid; elselimitup=mid; } update(ans,limitdn); for (ne=head[s],x=link[ne],me=ne^1;ne;ne=next[ne],x=link[ne],me=ne^1) { if (head[x]==me){ head[x]=next[me]; pre[next[me]]=0;} else{ next[pre[me]]=next[me]; pre[next[me]]=pre[me];} pre[me]=0;next[me]=0;link[me]=0;w[me]=0; getans(cal(x)); }}int main(){ freopen("rebuild.in","r",stdin); freopen("rebuild.out","w",stdout); scanf("%d%d%d",&n,&dn,&up); int i=0,u=0,v=0,tmpw=0; for (i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&tmpw); add(u,v,tmpw); } ans=-oo; getans(cal(1)); printf("%.3f",ans); return 0;}
- WC 2010 rebuild 重建计划
- MSSQL Rebuild(重建)索引
- 【Tsinghua】树重建(Rebuild)
- Elasticsearch索引重建(Rebuild)
- Elasticsearch索引重建(Rebuild)
- elasticsearch 索引重建(Rebuild)
- 重建索引:ALTER INDEX..REBUILD ONLINE vs ALTER INDEX..REBUILD
- SQL Server 重建索引 Rebuild Index
- 1758: [Wc2010]重建计划
- [BZOJ 1758]重建计划
- HYSBZ 1758 重建计划
- BZOJ1758 [WC2010]重建计划
- 1758: [Wc2010]重建计划
- bzoj1758 [Wc2010]重建计划
- sqlserver重建(rebuild)索引可以提高查询速度
- Oracle index rebuild online 与 rebuild 及 drop index 后重建
- 【BZOJ 1758】 [Wc2010]重建计划
- bzoj 1758: [Wc2010]重建计划
- 四则混合运算C++代码(中缀表达式)
- 求教,有关cocos2D纹理图释放问题
- Ruby / libcurl应用
- check/repair与myisamchk对比
- 高并发高流量网站架构
- WC 2010 rebuild 重建计划
- 说说大型高并发高负载网站的系统架构
- 关于高并发的思考
- mysql表的优化
- 手机横竖屏切换处理
- 三五杆枪,可干革命,三五个人,可以创业
- Android基础类之BaseAdapter
- asp.net如何在页面加载时响应回车事件
- 习惯是新型病毒:为什么创业者必须成为行为习惯专家