首页 > 其他分享 >P3571 [POI2014] SUP-Supercomputer 题解

P3571 [POI2014] SUP-Supercomputer 题解

时间:2024-10-19 15:44:06浏览次数:7  
标签:lceil le frac int 题解 Supercomputer max rceil P3571

P3571「POI2014」SUP-Supercomputer 题解

一道 “较” 水的黑题 (可一开始苦思冥想还是不会)

本蒟蒻的第一篇黑题题解,求赞。

题意简化

给定一棵 $n$ 个节点、根节点为 $1$ 的有根树。$q$ 次询问中每次给定一个 $k$,输出需要最少用几次操作次数 删除 完整棵树。每次操作可以选择 删除 不超过 $k$ 个未访问的点,且这些点 没有父亲(血腥的味道)

前置知识

有一个 小小 的结论:存在一个 $i$,满足可以用 $i$ 次操作删掉所有深度小于等于 $i$ 的点,剩下的操作每次都删掉 $k$ 个点。

形式化地,设 $f_k$ 为 $k$ 对应的答案,$s_i$ 是深度大于 $i$ 的点数,有:
$$
f_k=\max_i \lceil\frac{s_i}{k}\rceil+i
$$

  • Why?

显然 ,要证明 $f_k=\max_i \lceil\frac{s_i}{k}\rceil+i$,转换为不等式,可分别证明 $f_k\ge\max_i \lceil\frac{s_i}{k}\rceil+i$ 和 $f_k\le\max_i \lceil\frac{s_i}{k}\rceil+i$:

  1. 证明 $f_k\ge\max_i \lceil\frac{s_i}{k}\rceil+i$ :
    可以注意到一个性质,要删除至少一个深度为 $i$ 的点,至少需要 $i$ 次操作。那么有 $f_k\ge \max_i \lceil\frac{s_i}{k}\rceil+i$。

  2. 证明 $f_k\le\max_i \lceil\frac{s_i}{k}\rceil+i$ :
    设 $f_{k,i}=i+\lceil\frac{s_i}{k}\rceil$,$f_{k,i}$ 在 $i=a$ 时取最大值。我们假设 $b$ 步可以删除完前 $b$ 层的节点,且这是满足条件的最大的 $b$,即证 $a=b$。

    • 先证 $a\ge b$:对于 $c<b$,若 $f_{k,c}>f_{k,b}$,则深度范围在 $(c,b]$ 之间的点数大于 $k(b−c)$,删掉一个第 $c$ 层的点至少要 $c$ 步,删掉 $c+1$ 到 $b$ 层的所有点要大于 $(b−c)$ 步,那么前 $b$ 层肯定 $b$ 次删不完,矛盾。因此 $a\ge b$。

    • 再证 $a\le b$:

      1. 第 $b+1$ 层一定有超过 $k$ 个节点,$f_{k,b+1}\le f_{k,b}$。
      2. 若第 $b+1$,$b+2$ 层点数之和不超过 $2k$,那么第 $b+2$ 层的点数一定不足 $b+1$ 层的,我们可以 $b+2$ 次删除完前 $b+2$ 层,矛盾,因此第 $b+1$,$b+2$ 层点数之和大于 $2k$,$f_{k,b+2}\le f_{k,b}$。

      以此类推 $a\le b$。
      所以 $a=b$,即 $f_k\le\max_i \lceil\frac{s_i}{k}\rceil+i$。

根据上面对 $a\le b$ 的证明,可以归纳证明第 $b+1$ 到第 $b+t$ 层的点数之和大于 $kt$,于是我们只需要一层一层删掉,并优先删除有儿子的结点就一定可行。这样 $f_k=\max_i \lceil\frac{s_i}{k}\rceil+i$,证毕。

题目解法

嘿嘿,大脑有没有烧了呢?有了以上结论,这道题就可以 切了。

对 $f_k=\max_i \lceil\frac{s_i}{k}\rceil+i$ 进行变形:
$$
f_k=\max_i \lceil\frac{s_i}{k}\rceil+i=f_k= \max_i \lceil\frac{s_i+ki}{k}\rceil
$$
所以,只需求 $g_k=\max s_i+ki$ 。

则:$s_i=-ki+g_k$($y=kx+b$)。

斜率优化即可,横坐标和斜率都单调,复杂度 $\mathcal{O}(n)$。

参考代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,q[N],dep[N];
int sum[N],maxn,ans[N];
struct __{
    int x,y;
    bool operator<(const __ x)const{
        return y<x.y;
    }
}a[N];
double slp(int x,int y){
	if(x==y)return 1e9;
	return (sum[y+1]-sum[x+1])*1.0/(x-y);
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin>>n>>m;sum[1]=dep[1]=1;
	for(int i=1;i<=m;i++)
        cin>>a[i].y,a[i].x=i;
	stable_sort(a+1,a+m+1);
	for(int i=2,x;i<=n;i++){
		cin>>x; dep[i] = dep[x]+1;
		maxn = max(maxn , dep[i]);
		sum[dep[i]]=sum[dep[i]]+1;
	}
    for(int i=maxn;i>0;i--)
        sum[i]+=sum[i+1];
	int l=1,r=1;
	for(int i=1;i<=maxn;i++){
		while(l<r&&slp(i,q[r])<=slp(q[r],q[r-1]))
            r--;
		q[++r]=i;
	}
	for(int i=1;i<=m;i++){
		while(l<r&&a[i].y>slp(q[l],q[l+1]))
            l++;
        int k=q[l],Y=a[i].y,X=a[i].x;
		ans[X] = k+(sum[k+1]+Y-1)/Y ;
	}
	for(int i=1;i<=m;i++)
        cout<<ans[i]<<" ";
	return 0;
}

完 结 撒 花 ! ! !

标签:lceil,le,frac,int,题解,Supercomputer,max,rceil,P3571
From: https://www.cnblogs.com/zhanghaoran666-AK-IOI/p/18475969/P3571-Solution

相关文章

  • P6533 [COCI2015-2016#1] RELATIVNOST 题解
    考虑当$q=0$时怎么做。注意到性质$c\le20$,因此不妨正难则反,将**至少有$c$个人购买彩色画**的方案数转化为总方案数减去**不足$c$人购买彩色画的方案数**。这个是一个类似凑数的dp,不妨考虑背包。我们有$f_{i,j}$表示前$i$人中**恰好**$j$人购买彩色画的方......
  • [CF1616H] - Keep XOR Low 的题解
    一道比较神奇的题目,状态显得比较扯淡,但是就是能过!先建立出trie树,设\(dp_u\)表示以\(u\)为根的子树内的答案。但我们发现,若\(x\)的当前位为\(1\),那么问题就没法根据他的左右子树求解了,怎么办呢。考虑一个很扯淡的状态,设\(dp_{u,v}\)表示考虑了\(u,v\)为根的子树,他......
  • 牛客练习赛130-A题题解
    牛客练习赛130-A题题解题目描述如下:给定两个整数x,y,jackle希望把x变成y。他每次可以进行如下两种操作之一:选择任意一个整数z,令x=x&z。选择任意一个整数z,令x=x|z。请问最少操作几次可以把x变成y。输入描述:本题有多组测试数据。第一行输入1个正整数T(1≤T......
  • [ABC134F] Permutation Oddness 题解
    T5[ABC134F]PermutationOddness很无敌的一道题。(好像是我第一次用无敌这个词把\(p_i\)和\(i\)的对应关系转化为球和盒子的配对问题,则原式中的绝对值顺利成章地就变成类似距离的一个东西。那么设\(f_{i,j,k}\)表示前\(i\)个球和盒子(注意球和盒子是一起考虑的,所以\(i......
  • [ARC185D] Random Walk on Tree 题解
    一个很套路的做法。思路题目要求走完整个树的时间,这并不好算,容易想到min-max容斥。依据min-max容斥,我们可以轻松把它转化成第一次走到所有子集的时间。考虑在这道题中,有什么特殊的。第一,任何包含根节点的子集答案都是零。第二,由于我们只关心第一次走到的点的时间,因此假......
  • ZZJC新生训练赛第五场题解
    A题思路题目要求构造一个相邻两项互质的长度为n的序列。可以直接选择输出从1到n的自然数序列,因为相邻的自然数总是互质的。题目有多个测试用例,因此需要逐个处理输入,并输出对应结果。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_wit......
  • 题解:[YNOI2019] 游戏
    ProblemLink[YNOI2019]游戏题外话第一眼,由乃?不打不打。第二眼,欸noi三个字母怎么是大写(才发现是云南省选)。题意题意简洁,不再赘述。Solution一眼看出概率dp,但如何似乎没思路?开始公式做题:设置状态+推转移式。\(Q1\):怎么设置状态?首先,思考一个问题:第\(k\)个人该怎么“......
  • 异常问题解决
    异常:java程序编译或运行过程中出现的问题Throwable:Error:表示非常严重的问题,自己无法解决的问题Exception:除了RuntimeException其它异常【编译时期异常】:一般指的是异常尚未处理就编译了RuntimeException【运行时期异......
  • PTA L1系列题解(C语言)(L1_081 -- L1_088)
    L1-081今天我要赢题目内容:2018年我们曾经出过一题,是输出“2018我们要赢”。今年是2022年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。输入格式:本题没有输入。输出格式:输出分2行。在第一行中输出I'mgonnawin!Today!,在第二行中用年年年......
  • P1955 程序自动分析 题解
    P1955程序自动分析一道并查集的裸题,并查集存储传递性,后判断。主题思路十分简单,重点在于离散化与离线的处理。离散化,为什么会想到离散化呢,观察数据范围\(1<i,j<{10}^9\),数据范围过大,导致数组不可能开到\(1e9\)但是\(1<n<1e5\)考虑到每次输入只有两个数,若每个数都两两不同,......