Problem

辣鸡bzoj权限题,洛谷链接

题意概要:一棵 \(n\) 个点有根树。\(Q\) 次询问给出一个 \(K\),回答遍历完整棵树所需最少操作次数。每次操作可以选择访问不超过 \(K\) 个未访问的点,且这些点的父亲必须在之前被访问过。

Solution

一开始题意理解错了,以为同时段每个点都能扩展 \(k\) 次,然后就无耻地看了题解……但是有个证明网上都没写,这也正是写这篇博客的原因

大概意思是说,最优策略一定是先用 \(i\) 步取完前 \(i\) 层,然后选取剩下深度大于 \(i\) 的节点时每次都能取满。规范一下就是设 \(s[i]\) 表示深度大于 \(i\) 的节点个数,则答案为 \(\max\limits_{i=1}^n \{i+\lceil \frac {s[i]}k\rceil\}\)

然后就可以正常斜率优化了:维护点 \((i,s[i])\) 的上凸包,每次询问 \(i\) 则在凸包上找斜率为 \(-i\) 的直线所切的点

但是看题解的时候不清楚前边那个式子的正确性,为什么会存在一条分界线使得上面可以用 \(i\) 次选完 \(i\) 层,下面可以随意选

思考了一会才弄懂,对于一棵树,从底层选择一个最深的深度 \(d\),显然满足下部节点可以随意选择(目前没有下部节点),但是有可能上部节点不能在层数次内选完。若出现这种情况,则上部一定存在若干层节点特别多,导致无法消完,可以考虑将分界线挪到某一层的上一层,由于这层节点特别多,可以保证下部节点可以随意选择。所以存在分界线比深度 \(d\) 浅,将 \(d\) 减小继续判断直到无法挪动,则找到分界线

至于为什么 \(\max\limits_{i=1}^n \{i+\lceil \frac {s[i]}k\rceil\}\) 中取最大值即可,是因为如若没有选择到分界线,则算出的值一定比最终答案要小

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db; template <typename _tp> inline void read(_tp&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
} const int N = 1001000;
struct Edge{int v,nxt;} a[N+N];
int head[N], s[N], Ans[N], qy[N];
ll f[N];
int n,Q,tp,_,mxd; void dfs(int x,int ds){
++s[ds], mxd = max(mxd, ds);
for(int i=head[x];i;i=a[i].nxt)
dfs(a[i].v,ds+1);
} struct vec{
ll x,y;
inline void in(){read(x), read(y);}
friend inline vec operator - (const vec&A,const vec&B) {return (vec){A.x - B.x, A.y - B.y};}
friend inline db operator * (const vec&A,const vec&B) {return (db)A.x * B.y - (db)A.y * B.x;}
friend inline bool operator < (const vec&A,const vec&B) {return A.x!=B.x ? A.x<B.x : A.y>B.y;}
}p[N],stk[N]; int main(){
read(n), read(Q);
for(int i=1;i<=Q;++i) read(qy[i]);
for(int i=2,x;i<=n;++i) read(x), a[++_].v = i, a[_].nxt = head[x], head[x] = _;
dfs(1,0);
for(int i=n;~i;--i) s[i] += s[i+1];
for(int i=0;;++i){
vec nw = (vec) {i, s[i]};
while(tp > 1 and (stk[tp] - stk[tp-1]) * (nw - stk[tp]) >= 0) --tp;
stk[++tp] = nw;
if(!s[i]) break;
}
for(int i=1,t=1;i<=n;++i){
vec dir = (vec) {1, -i};
while(t < tp and (stk[t+1] - stk[t]) * dir < 0) ++t;
Ans[i] = (stk[t].y + (ll)i * stk[t].x + i-1) / i;
}
++mxd;
for(int i=1;i<=Q;++i){
if(Ans[qy[i]]) printf("%d ",Ans[qy[i]]);
else printf("%d ",mxd);
}
return 0;
}

题解-POI2014 Supercomputer的更多相关文章

  1. 【BZOJ】3835: [Poi2014]Supercomputer

    题意 \(n(1 \le 1000000)\)个点的有根树,\(1\)号点为根,\(q(1 \le 1000000)\)次询问,每次给一个\(k\),每一次可以选择\(k\)个未访问的点,且父亲是访问 ...

  2. BZOJ3835: [Poi2014]Supercomputer

    Description Byteasar has designed a supercomputer of novel architecture. It may comprise of many (id ...

  3. BZOJ3835[Poi2014]Supercomputer——斜率优化

    题目描述 Byteasar has designed a supercomputer of novel architecture. It may comprise of many (identical ...

  4. BZOJ3835 [Poi2014]Supercomputer 【斜率优化】

    题目链接 BZOJ3835 题解 对于\(k\),设\(s[i]\)为深度大于\(i\)的点数 \[ans = max\{i + \lceil \frac{s[i]}{k}\} \rceil\] 最优 ...

  5. 题解-POI2014 FAR-FarmCraft

    Problem bzoj权限题,洛谷上可提交 洛谷上的奇葩翻译不要看,很多条件缺漏 题意简述:给定一棵树,每条边权为1,给定所有点点权,每条边仅能走两次,求以一定顺序遍历整棵树后,使所有点中的到达时间 ...

  6. [POI2014]Supercomputer

    题目大意: 给定一个$n(n\le10^6)$个结点的有根树,从根结点开始染色.每次可以染和已染色结点相邻的任意$k$个结点.$q(q\le10^6)$组询问,每次给定$k$,问至少需要染几次? 思路 ...

  7. POI2014题解

    POI2014题解 [BZOJ3521][Poi2014]Salad Bar 把p当作\(1\),把j当作\(-1\),然后做一遍前缀和. 一个合法区间\([l,r]\)要满足条件就需要满足所有前缀和 ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. BZOJ3524 & LOJ2432:[POI2014]代理商Couriers——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3524 https://loj.ac/problem/2432 给一个长度为n的序列a.1≤a[i] ...

随机推荐

  1. PHP为前端CSS和JS增加时间戳版本号

    一.PHP代码如下: function addVersion($url){ $version = date("Y-m-d H:i:s",filemtime($_SERVER['DO ...

  2. iis500错误分析

    1.检查isapi和cgi限制,看相应的扩展是否设为允许. 2.让错误显示到客户端 3.HTTP 错误 500.21 - Internal Server Error 原因:在安装Framework v ...

  3. python面对对象(不全解)

    面对对象:以人类为例,人类通用功能:吃喝拉撒,就可以封装成一个类,不同功能:嫖赌毒,就是对象的不同功能.继承,多态… 上码 class Person(object): def __init__(sel ...

  4. Linux C启动时创建pid文件

    程序在启动时将pid写入文件,当程序再次启动时会进行检测,避免启动多个实例. util-pidfile.h文件 #ifndef __UTIL_PID_H__ #define __UTIL_PID_H_ ...

  5. 极简Python DeBug工具——PySnooper

    DeBug Python 代码的方式有很多种?比如: (1)设置断点 (2)print函数 (3)... 本文要介绍的是一个新开源的项目PySnooper ,只要给有疑问的代码加上装饰器,各种信息一目 ...

  6. POJ1847 Tram

    Tram Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 20274   Accepted: 7553 Description ...

  7. PL2303HX在Windows 10下面不装安装驱动的解决办法(Code:10)

    Prolific在很早之前推出了一款名为PL2303HX的芯片, 用于USB转RS232, 这款芯片使用的范围非常广, 并且年代久远. 但是这款芯片因为用的特别多, 所以中国就有很多厂家生产了仿造的P ...

  8. Vue组件开发

    在学习vue的时候,发现有很多使用vue开发的ui组件.本着学习的目的,自己也仿照Element写一些组件. 使用VuePress编写组件文档. 单元测试:karma+mocha+chai+sinon ...

  9. Spring MVC 使用介绍(十五)数据验证 (二)依赖注入与方法级别验证

    一.概述 JSR-349 (Bean Validation 1.1)对数据验证进一步进行的规范,主要内容如下: 1.依赖注入验证 2.方法级别验证 二.依赖注入验证 spring提供BeanValid ...

  10. Flask 构建微电影视频网站(七)

    电影模块实现 上映预告 @home.route("/animation/") def animation(): """ 首页轮播动画 "&q ...