博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P2680 运输计划(树上差分+二分)
阅读量:6153 次
发布时间:2019-06-21

本文共 1645 字,大约阅读时间需要 5 分钟。

 

考虑树上乱搞

首先这是满足二分性质的,如果在某个时间可以完成工作那么比他更长的时间肯定也能完成工作

然后考虑二分,设当前答案为$mid$,如果有一条链的长度大于$mid$,那么这条链上必须得删去一条边。我们可以贪心的删去所有可以删去的边中最长的,然后看看最长边减去删去的边是否小于等于$mid$,如果成立说明可行

然后考虑怎么solve,我们可以用树上差分,就是对于每个点把它看做他父亲到他的边,每个点记录一个$s$,然后对于一条链,两个端点++,lca-=2。如果有一个点的$s$等于大于$mid$的链的条数,说明它被所有的链给覆盖,然后求一个最大值就好了

然后每一条链的lca都要求出来……实际上直接每一条都$O(logn)$求出来也没关系……不过代码里用的是tarjan离线求的,所以复杂度是$O(n+m)$

总复杂度是$O(nlogn)$(复杂度并没有降……直接树剖求LCA可能更省力啊……)

1 //minamoto 2 #include
3 #include
4 #include
5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 template
inline bool cmax(T&a,const T&b){
return a
x){51 q[i].solve(),++num;52 }53 dfs(1,0);54 return mx-res<=x;55 }56 void tarjan(int u,int ff){57 for(int i=head[u];i;i=Next[i]){58 int v=ver[i];59 if(v==ff) continue;60 dis[v]=dis[u]+edge[i];61 tarjan(v,u);62 a[v]=edge[i];63 int f1=find(v),f2=find(u);64 if(f1!=f2) fa[f1]=f2;65 vis[v]=1;66 }67 for(int i=hq[u];i;i=nq[i]){68 int v=vq[i];69 if(vis[v]){70 int p=(i+1)>>1,LCA=find(v);71 q[p]=node(u,v,dis[u]+dis[v]-2*dis[LCA],LCA);72 cmax(mx,q[p].len);73 }74 }75 }76 int main(){77 // freopen("testdata.in","r",stdin);78 n=read(),m=read();79 for(int i=1,u,v,e;i
>1;88 if(check(mid)) r=mid-1,ans=mid;89 else l=mid+1;90 }91 printf("%d\n",ans);92 return 0;93 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9677581.html

你可能感兴趣的文章
Unity3D 与udk 3D游戏动漫引擎的开发特点
查看>>
jsp页面与ActionForm数据交互的原理
查看>>
同一首歌
查看>>
记壹次不愉快的使用医保卡的经历
查看>>
CSS 渲染样式优先级(选择器优先级)
查看>>
apache编译故障-apr-not-found.docx
查看>>
多线程读写链表 pthread
查看>>
Maven的dependencyManagement
查看>>
数组分类:关联数组,索引数组
查看>>
NSURLConnection
查看>>
广告系统常见实体和属性
查看>>
IT 事业发展:保卫您的 IT 职业生涯
查看>>
详述cookie及其使用
查看>>
我的友情链接
查看>>
大学计算机软件专业生应该学什么
查看>>
.Net开源的MongoDB可视化管理工具 MongoCola
查看>>
Host storage devices vulnerable with KVM Linux ...
查看>>
SpringMVC的拦截器
查看>>
模版邮件内容配置
查看>>
关闭窗口,不提示关闭提示对话框
查看>>