#include <iostream>
#include <cstring>
using namespace std;
const int N = 100001;
int main(){
int L[N], R[N];
int b[N], s[N];
memset(b, 0, sizeof(b));
memset(s, 0, sizeof(s));
int n, m, cnt = 0;
cin >> n >> m;
for(int i = 1; i <= m; i++){ //这个循环和“b[i] += b[i - 1];”用于修改区间的值
cin >> L[i] >> R[i];
b[L[i]]++;
b[R[i] + 1]--;
}
for(int i = 1; i <= n; i++){
b[i] += b[i - 1];
s[i] = s[i - 1] + (b[i] == 1);//s[i]用于统计从0到i总共有多少b[i]==1的点
cnt += (b[i] == 0);//cnt用于统计没被覆盖的点
}
int now = 0, min = 1000000, ans = 1;
for(int i = 1; i <= m; i++){
now = s[R[i]] - s[L[i] - 1]; //now用于储存每条线段覆盖值为1的点的个数
if(now <= min){
min = now;
ans = i;
}
}
cout << ans << " " << min + cnt << endl;
return 0;
}
牛客练习赛34_C题题解 |
这个题目,我的思路是统计被覆盖次数最多的点,因为这样就可以保证删掉线段对其没有影响,现在想来,这种思路不仅错解了题意,而且根本就没有任何意义。
正确的思路就是顺着题意来,即统计只被线段覆盖过一次的点,然后看哪条线段所覆盖区间中只被覆盖过一次的点的个数最少,用min统计,然后加上被覆盖过零次的点就可以输出了。这道题关于差分数组和前缀和的解释见如下博客:
https://gydjsz.github.io/2018/12/22/algorithm/nowcoderPractice34/