牛客小白月赛99 E题
多米诺骨牌
题目背景
牛客小白月赛99
题目描述
样例 #1
样例输入 #1
3
6 1
1 1 1 3 2 1
4 3 2 7 9 11
6 2
1 1 1 3 2 1
4 3 2 7 9 11
5 4
1 4 1 1 2
1 2 3 6 8
样例输出 #1
3
6
5
做题思路
按照玩多米诺骨牌的方式。
先将多米诺骨牌按照骨牌位置从小到大排序,相当于摆放好多米诺骨牌。
接着从第一个多米诺骨牌遍历到最后一个多米诺骨牌。
在此期间如果第 i i i个多米诺骨牌的位置在 i − 1 i-1 i−1个多米诺骨牌的倒下范围内,那么“这一堆”多米诺骨牌倒下的个数+1 ; 否则从新开“一堆”多米诺骨牌,并且设置多米诺骨牌倒下个数为1。
最后按照从大到小顺序对“每一堆”多米诺骨牌倒下个数进行排序。
最后取 m i n ( m , 堆数 ) min(m,堆数) min(m,堆数)次多米诺骨牌倒下个数的和作为答案即可。
核心代码:
for(int i=1;i<=n;i++){
if(i == 1 || dmn[i].x > last){ // 是第一个多米诺骨牌||不会被前面连带推倒
sum[++cnt] = 1;//“这一堆”多米诺骨牌倒下个数设为1
last = max(last , dmn[i].x + dmn[i].h);//维护多米诺骨牌倒下范围最大值
}
else{
sum[cnt] ++;//“这一堆”多米诺骨牌倒下个数加一
last = max(last , dmn[i].x + dmn[i].h);
}
}
代码
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int N = 2e7+10;
int n , m ,k , w , q;
int cnt , sum[N];
struct Dmn{
int h , x;
}dmn[N];
void init(){}
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void solve(){
n=read();m=read();
for(int i=1;i<=n;i++){
dmn[i].h = read();
}
for(int i=1;i<=n;i++){
dmn[i].x = read();
}
sort(dmn+1,dmn+1+n,[&](Dmn a , Dmn b){return a.x < b.x;});
cnt = 0;
int last = 0;
for(int i=1;i<=n;i++){
if(i == 1 || dmn[i].x > last){ // 是第一个多米诺骨牌||不会被前面连带推倒
sum[++cnt] = 1;//“这一堆”多米诺骨牌倒下个数设为1
last = max(last , dmn[i].x + dmn[i].h);//维护多米诺骨牌倒下范围最大值
}
else{
sum[cnt] ++;//“这一堆”多米诺骨牌倒下个数加一
last = max(last , dmn[i].x + dmn[i].h);
}
}
sort(sum+1,sum+cnt+1,greater<int>());
int ans = 0;
for(int i=1;i<=min(cnt,m);i++)ans+=sum[i];
cout << ans << '\n';
}
signed main(){
init();
int _=1;_=read();
while(_--)solve();
return 0;
}