BZOJ3672: [Noi2014]购票 树分治 斜率优化
来源:互联网 发布:9788 微信 网络不稳定 编辑:程序博客网 时间:2024/04/30 03:11
http://www.lydsy.com/JudgeOnline/problem.php?id=3672
树上的CDQ分治。
和常规CDQ思路相同,一个点的可行决策点是从这个点往上连续一段,那么在分治过程中先递归重心往上的一块(包括重心这个点),再将其他点按可行深度排序,然后维护上面那些点的凸包来更新底下点的答案,最后分别递归底下的块即可。
#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<functional>#include<algorithm>#define gm 200001using namespace std;typedef long long ll;int n,p[gm],fa[gm],t;ll q[gm],l[gm],dep[gm];bool ban[gm];struct e{ int t; e *n; ll c; e(int t,e *n,const ll& c):t(t),n(n),c(c){}}*f[gm];void init(int x){for(e *i=f[x];i;i=i->n){dep[i->t]=dep[x]+i->c,init(i->t);}}struct pnt{ ll x,y; pnt(const ll &x,const ll &y):x(x),y(y){} ll b(int k){return y-k*x;}};double slope(const pnt &a,const pnt &b){return (double)(a.y-b.y)/(a.x-b.x);}struct hull{ vector<pnt> p; vector<double> d; int sz; hull():p(),d(),sz(){} ~hull()=default; void push_back(const pnt &a) { if(!sz) { p.push_back(a); d.push_back(1e100); sz=1; } else { while(sz>1&&slope(p[sz-1],a)>d[sz-1]) { --sz; p.pop_back(); d.pop_back(); } p.push_back(a); d.push_back(slope(p[sz-1],a)); ++sz; } } ll find(const ll &k) { int pos=upper_bound(d.begin(),d.end(),(double)k,greater<double>())-d.begin()-1; return p[pos].b(k); } bool empty() {return !sz;}};ll dp[gm];int sz[gm];int lim,g;void dfs(int x){ bool is=1; sz[x]=1; for(e *i=f[x];i;i=i->n) { if(ban[i->t]) continue; dfs(i->t); if(sz[i->t]>lim>>1) is=0; sz[x]+=sz[i->t]; } if(lim-sz[x]>lim>>1) is=0; if(is) g=x;}int r[gm],cnt;void push(int x){ r[++cnt]=x; for(e *i=f[x];i;i=i->n) { if(ban[i->t]) continue; push(i->t); }}struct cmp{bool operator() (int a,int b){return dep[a]-l[a]>dep[b]-l[b];}};void solve(int rt,int tot){ lim=tot; dfs(rt); int x=g; vector<int> lst; for(e *i=f[x];i;i=i->n) { if(ban[i->t]) continue; ban[i->t]=1; lst.push_back(i->t); tot-=sz[i->t]; } if(rt!=x) solve(rt,tot); ban[x]=1;cnt=0; for(vector<int>::iterator it=lst.begin();it!=lst.end();++it){ban[*it]=0; push(*it);} sort(r+1,r+cnt+1,cmp()); hull h; for(int i=1;i<=cnt;++i) { int y=r[i]; while(x!=fa[rt]&&dep[x]>=dep[y]-l[y]) h.push_back(pnt(dep[x],dp[x])),x=fa[x]; if(!h.empty()) { ll kre=h.find(p[y]); dp[y]=min(dp[y],kre+p[y]*dep[y]+q[y]); } } for(vector<int>::iterator it=lst.begin();it!=lst.end();++it){solve(*it,sz[*it]);}}int main(){ scanf("%d%d",&n,&t); memset(dp+1,0x7f,n<<3); dp[1]=0; for(int i=2;i<=n;++i) { ll len; scanf("%d%lld%d%lld%lld",fa+i,&len,p+i,q+i,l+i); f[fa[i]]=new e(i,f[fa[i]],len); } init(1); solve(1,n); for(int i=2;i<=n;++i) printf("%lld\n",dp[i]); return 0;}
阅读全文
0 0
- [BZOJ3672][NOI2014]购票 树分治斜率优化
- BZOJ3672: [Noi2014]购票 树分治 斜率优化
- [BZOJ3672][NOI2014]购票-点分治-CDQ分治-斜率优化DP
- BZOJ3672:[Noi2014]购票 (斜率优化DP+二分+(树上CDQ分治/树链剖分))
- 【bzoj3672】[Noi2014]购票 斜率优化+树链剖分+线段树+凸包+三分
- BZOJ 3672 NOI2014 购票 树的点分治+斜率优化
- 【BZOJ 3672】[Noi2014]购票 树分治+斜率优化
- 【BZOJ 3672】[Noi2014]购票 树分治+斜率优化
- 【NOI2014】【cdq点分治】【斜率优化】购票
- bzoj3672 [ NOI2014 ] -- 树上CDQ分治 + 斜率优化DP
- bzoj3672: [Noi2014]购票
- 【bzoj3672&&uoj7】[Noi2014]购票
- bzoj3672: [Noi2014]购票
- bzoj3672 [Noi2014]购票
- BZOJ3672: [Noi2014]购票
- 3672: [Noi2014]购票 树剖+线段树+斜率优化
- BZOJ 3672 [Noi2014]购票【点分+斜率优化
- 树上CDQ分治 NOI2014购票
- 散列表(Hash table)
- 聊聊左闭右开区间
- vim多文件复制粘贴
- 53 C语言逻辑运算符
- 【Redis】redis两种备份方式
- BZOJ3672: [Noi2014]购票 树分治 斜率优化
- [速成]了解一致性hash算法
- android studio快捷键使用
- 大话设计模式阅读笔记-装饰模式
- 半导体存储器详细搬运总结:关于RAM,ROM和硬盘
- R语言向量_向量元素的名称
- 举例urlopen中的data用法
- Android 深入理解Android中的自定义属性
- 在windows10下面 modelsim10.1a的安装