CF1561C Deep Down Below 题解
题目
链接
https://www.luogu.com.cn/problem/CF1561C
字面描述
Deep Down Below
题面翻译
T T T 组数据,每次给定 n n n 个任务,第 i i i 个任务给定 k i k_i ki 个怪物,每个怪物有一个能力值 a i , j a_{i,j} ai,j 你要按顺序把这 k i k_i ki 个怪物杀死,你能杀死一个怪物当且仅当你的能力值严格大于怪物的能力值,杀死一个怪物后,你的能力值将会 + 1 +1 +1。
你可以按任意顺序完成这 n n n 个任务,你需要确定最小的初始能力值。
T ≤ 1 0 5 , n ≤ 1 0 5 , k i ≤ 1 0 5 , ∑ k i ≤ 1 0 5 , a i , j ≤ 1 0 9 T\leq 10^5,n\leq 10^5,k_i\leq10^5,\sum k_i\leq 10^5,a_{i,j}\leq 10^9 T≤105,n≤105,ki≤105,∑ki≤105,ai,j≤109。
题目描述
In a certain video game, the player controls a hero characterized by a single integer value: power. The hero will have to beat monsters that are also characterized by a single integer value: armor.
On the current level, the hero is facing $ n $ caves. To pass the level, the hero must enter all the caves in some order, each cave exactly once, and exit every cave safe and sound. When the hero enters cave $ i $ , he will have to fight $ k_i $ monsters in a row: first a monster with armor $ a_{i, 1} $ , then a monster with armor $ a_{i, 2} $ and so on, finally, a monster with armor $ a_{i, k_i} $ .
The hero can beat a monster if and only if the hero’s power is strictly greater than the monster’s armor. If the hero can’t beat the monster he’s fighting, the game ends and the player loses. Note that once the hero enters a cave, he can’t exit it before he fights all the monsters in it, strictly in the given order.
Each time the hero beats a monster, the hero’s power increases by $ 1 $ .
Find the smallest possible power the hero must start the level with to be able to enter all the caves in some order and beat all the monsters.
输入格式
Each test contains multiple test cases. The first line contains the number of test cases $ t $ ( $ 1 \le t \le 10^5 $ ). Description of the test cases follows.
The first line of each test case contains a single integer $ n $ ( $ 1 \le n \le 10^5 $ ) — the number of caves.
The $ i $ -th of the next $ n $ lines contains an integer $ k_i $ ( $ 1 \le k_i \le 10^5 $ ) — the number of monsters in the $ i $ -th cave, followed by $ k_i $ integers $ a_{i, 1}, a_{i, 2}, \ldots, a_{i, k_i} $ ( $ 1 \le a_{i, j} \le 10^9 $ ) — armor levels of the monsters in cave $ i $ in order the hero has to fight them.
It is guaranteed that the sum of $ k_i $ over all test cases does not exceed $ 10^5 $ .
输出格式
For each test case print a single integer — the smallest possible power the hero must start the level with to be able to enter all the caves in some order and beat all the monsters.
样例 #1
样例输入 #1
2
1
1 42
2
3 10 15 8
2 12 11
样例输出 #1
43
13
提示
In the first test case, the hero has to beat a single monster with armor $ 42 $ , it’s enough to have power $ 43 $ to achieve that.
In the second test case, the hero can pass the level with initial power $ 13 $ as follows:
- enter cave $ 2 $ :
- beat a monster with armor $ 12 $ , power increases to $ 14 $ ;
- beat a monster with armor $ 11 $ , power increases to $ 15 $ ;
- enter cave $ 1 $ :
- beat a monster with armor $ 10 $ , power increases to $ 16 $ ;
- beat a monster with armor $ 15 $ , power increases to $ 17 $ ;
- beat a monster with armor $ 8 $ , power increases to $ 18 $ .
思路
TLE算法
具体思想
本人最初的想法十分的朴素,针对 n n n个任务维护 n n n个队首指针。
- 每次比较出 n n n个任务队首怪兽的最小值
- 与当前预算的能力值比较是否能继续打怪,是 -> 继续 ,否 -> 加到怪兽能力值+1即可。
TLE特例
如果有1e5个任务,每个任务只有1个怪兽。
按此算法:
时间复杂度退化: O ( n ⋅ Σ k ) ≈ 1 e 10 O(n·Σk)≈1e10 O(n⋅Σk)≈1e10 TLE ! ! !
AC思想
2阶段处理
- 算出每组打怪加能力的情况下每一个怪兽所对应初始能力值,并取max
- 将 n n n个max从小到大排序,依次循环,看每个max加上对应任务里的元素数(能加多少次能力),是否能满足下一个max,是 -> continue ,否 -> 加到下一个max。
时间复杂度: O ( Σ k ⋅ l o g ( Σ k ) ) ≈ 2 e 6 O(Σk·log(Σk))≈2e6 O(Σk⋅log(Σk))≈2e6
阶段线性处理,tql !
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int t,n,ans;
int k[maxn];
vector<int>e[maxn];
struct node{
int v,cnt;
}a[maxn];
inline bool cmp(node p,node q){return p.v<q.v;}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
e[i].clear();
scanf("%d",&k[i]);
//算每组的最大值
for(int j=1;j<=k[i];j++){
int x;
scanf("%d",&x);
x=x+2-j;
if(j!=1)x=max(x,e[i][j-2]);
e[i].push_back(x);
}
a[i].v=e[i][k[i]-1];//最大值的最小取值
a[i].cnt=k[i];//任务里的怪兽数
//printf("%d = %d %d\n",i,a[i].v,a[i].cnt);
}
sort(a+1,a+n+1,cmp);
ans=a[1].v;
int l=ans+a[1].cnt;
//排序比较
for(int i=2;i<=n;i++){
if(l<a[i].v){
ans=ans+a[i].v-l;
l=a[i].v;
}
l+=a[i].cnt;
}
printf("%d\n",ans);
}
return 0;
}
备注
写入好题本