链接:https://ac.nowcoder.com/acm/contest/297/C
来源:牛客网
题目描述
小w有m条线段,编号为1到m。
用这些线段覆盖数轴上的n个点,编号为1到n。
第i条线段覆盖数轴上的区间是L[i],R[i]。
覆盖的区间可能会有重叠,而且不保证m条线段一定能覆盖所有n个点。
现在小w不小心丢失了一条线段,请问丢失哪条线段,使数轴上没被覆盖到的点的个数尽可能少,请输出丢失的线段的编号和没被覆盖到的点的个数。如果有多条线段符合要求,请输出编号最大线段的编号(编号为1到m)。
输入描述:
第一行包括两个正整数n,m(1≤n,m≤10^5)。 接下来m行,每行包括两个正整数L[i],R[i](1≤L[i]≤R[i]≤n)。
输出描述:
输出一行,包括两个整数a b。 a表示丢失的线段的编号。 b表示丢失了第a条线段后,没被覆盖到的点的个数。
示例1
输入
复制
5 3 1 3 4 5 3 4
输出
复制
3 0
说明
若丢失第1条线段,1和2没被线段覆盖到。 若丢失第2条线段,5没被线段覆盖到。 若丢失第3条线段,所有点都被线段覆盖到了。
示例2
输入
复制
6 2 1 2 4 5
输出
复制
2 4
说明
若丢失第1条线段,1,2,3,6没被线段覆盖到。 若丢失第2条线段,3,4,5,6没被线段覆盖到。
这个玩意,用数组模拟,
做这道题,一开始用的是类似于贪心的算法,数据过了百分之八十七点一,之后,无论怎么坐,tm的,就是不会过了,
创造了很多样例也都过了,最后,零鸡移动,想到了这么个情况:
10 3
1 7
3 5
2 6
一试果然,答案错了
最后万般无奈之下,小小滴看了ac代码,茅厕顿开,原来是用数组模拟数轴,数据范围在十万以内,用数组模拟数轴,然后记录每个点所被覆盖的线段的个数,和未被一条边覆盖的点的个数r,然后统计,前缀中所有只被一条线段覆盖的个数。最后根据这个,寻找单独覆盖点数最少的那个线段l,最少为n,最后结果为l,n+r;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int s[100005]={0};
int dp[100004]={0};
struct node
{
int x,y;
}a[100006];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
a[0].x=0;
a[0].y=0;
int l,r;
int p;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
s[a[i].x]++;;
s[a[i].y+1]--;
}
int sz=0;
for(int i=1;i<=n;i++)
{
s[i]+=s[i-1];
sz+=(s[i]==0);
}
for(int i=1;i<=n;i++)
{
dp[i]=dp[i-1]+(s[i]==1);前缀
}
int mn=0x3f3f3f3f;
for(int i=1;i<=m;i++)///寻找单独覆盖点数最少的点
{
int t=dp[a[i].y]-dp[a[i].x-1];
if(mn>=t)
{
p=i;
mn=t;
}
}
printf("%d %d\n",p,mn+sz);
return 0;
}