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. VS2019 离线安装方法详解

    本文详细介绍了 VS2019 离线安装的相关步骤,以桌面开发为主下载 C++桌面开发..NET 桌面开发相关的工作负载.MFC 可选组件及帮助查看器. 工作负载(Workload) 离线安装需要先根据 ...

  2. Pod install Error List

    1. Error installing Crashlytics while executing pod install [!] Error installing Crashlytics [!] /us ...

  3. JPA javax.persistence.TransactionRequiredException

    直接说一下解决方案 Dao层,一定要是Dao层. 1 增加Transactional,必须要事务! 2 增加Modifying,告诉jpa这是修改! @Transactional @Modifying ...

  4. BZOJ2655calc

    题目描述 一个序列a1,...,an是合法的,当且仅当:长度为给定的n.a1,...,an都是[1,A]中的整数.a1,...,an互不相等.一个序列的值定义为它里面所有数的乘积,即a1a2...an ...

  5. 20175221 《Java程序设计》第8周学习总结

    20175221   <Java程序设计>第8周学习总结 教材学习内容总结 第十五章主要内容有:泛型.链表.堆栈.散列映射.树集以及树映射. 泛型: 声明:可以使用class名称<泛 ...

  6. EditText以及登录UI实现

    EditText是可以输入的文本框 <?xml version="1.0" encoding="utf-8"?><RelativeLayout ...

  7. 微信小程序与webview交互实现支付

    实现原理:点击h5网页的支付按钮——(跳转)——>嵌套改h5的小程序的支付页面——(处理支付)——>跳转至支付完成后的页面 注意:(1)网页h5中,引入微信的jssdk <scrip ...

  8. python7 数据类型的相互转化 字符编码

    复习 1.深浅拷贝    ls = [1, 'a', [10]]    值拷贝:直接赋值 ls1 = ls, ls中的任何值发生改变,ls1中的值都会随之改变    浅拷贝:通过copy()方法 ls ...

  9. CountDownLatch、CyclicBarrier、Semaphore共同之处与区别以及各自使用场景

    区别 CountDownLatch 使一个线程A或是组线程A等待其它线程执行完毕后,一个线程A或是组线程A才继续执行.CyclicBarrier:一组线程使用await()指定barrier,所有线程 ...

  10. [图解Java]ReentrantLock重入锁

    图解ReentrantLock 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把Reentran ...