CF1561C Deep Down Below

分析

首先可以确定的两点是:

  • 每个洞穴是互不干扰的。也就是说,第 ii 个洞穴能否通过,只和来第 ii 个洞穴前的 poweripower_i 有关。

  • 必然存在一个 poweripower_i',使得 poweri<poweripower_i<power_i' 时,过不了这个山洞;poweripoweripower_i\ge power_i' 时,能过这个山洞。

既然这样,我们就可以预处理出能过第 ii 个洞穴的最小的 poweripower_i

如何求呢?我们先给 poweripower_i 赋一个最小值 00,一个一个地经过怪物,面对怪物 ai,ja_{i,j} 时,英雄的 powerpowerpoweri+j1power_i+j-1,如果 poweri+j1<ai,j+1power_i+j-1<a_{i,j}+1,说明 poweripower_i 太小了,我们要把它调到符合要求的最小值 poweri+j1=ai,j+1power_i+j-1=a_{i,j}+1,也就是令 poweriai,j+2jpower_i\Leftarrow a_{i,j}+2-j

经过第 ii 个洞穴的所有怪物后,我们就得到了第 ii 个洞穴需要的最小的 poweripower_i

接下来我们要求经过所有洞穴需要的最小力量 ansans,我们可以把每个洞穴按照 poweripower_i 从小到大排序,排序时带上洞穴的怪物数量 kik_i

接下来我们一个一个经过山洞 ii,并记录前 i1i-1 个山洞的怪物数量前缀和 sumi1sum_{i-1}

然后和前面怪物的计算方法一样,把山洞当成怪物,面对山洞 ii 时,英雄的 powerpowerans+sumi1ans+sum_{i-1},如果 ans+sumi1<powerians+sum_{i-1}<power_i,说明 ansans 太小了,我们要把它调到符合要求的最小值 ans+sumi1=powerians+sum_{i-1}=power_i,也就是令 anspowerisumi1ans\Leftarrow power_i-sum_{i-1}

最后的 ansans 即为所求。

时间复杂度 O(tnlogn)O(tn\log n),主要是排序。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n,ans,a_i_j,sum;
struct asdf{
	int power,k;
}b[N];
bool cmp(asdf x,asdf y){
	return x.power<y.power;
}
int main(){
    scanf("%d",&t);
    while(t--){
    	scanf("%d",&n);
    	ans=sum=0;
    	for(int i=1;i<=n;i++){
    		b[i].power=0;
    		scanf("%d",&b[i].k);
    		for(int j=1;j<=b[i].k;j++){
    			scanf("%d",&a_i_j);
    			b[i].power=max(b[i].power,a_i_j+2-j);
			}
		}
		sort(b+1,b+n+1,cmp);
		for(int i=1;i<=n;i++){
			ans=max(ans,b[i].power-sum);
			sum+=b[i].k;
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2021-08-25 14:26  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源