首先,我们可以算出此分数的最高排名和最低排名,即 ai+1,n-bi;
然后根据题意我们可以明显去除一定错误的情况。
- 人数超过n:ai+bi+1>=n;
- 在[l,r]的人数超过 l-r+1。
我们再考虑区间不完全重合的情况,[a,b],[b,c],根据题意可知a=b>c&&a>b=c,冲突。
但区间完全重合是有可能的。
之后 我们可以按照右端点为第一关键字,左端点为第二关键字排序。
设f[i]为到第 i 个区间的最优值,f[i]=max(f[j])+value[i];
O()求解,但max(f[i])可用线段树维护达到O(nlgn)的复杂度。
但是线段树太麻烦了,
我们重新定义f[i],f[i]为到第i个点的最优值,若i为右端点则,j为当前区间。
最后输出n-f[n];
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
int read()
{
int sum=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch<='9'&&ch>='0')
{
sum=sum*10+ch-'0';
ch=getchar();
}
return sum;
}
struct node
{
int l,r;
}p[maxn];
int cmp(node x,node y)
{
if(x.r!=y.r) return x.r<y.r;
return x.l<y.l;
}
int n,num,t,w[maxn],L[maxn],R[maxn];
int f[maxn];
int main()
{
n=read();
for(int x,y,i=1;i<=n;i++)
{
x=read();y=read();
if(x+y>=n) continue;
t++;
p[t].l=x+1;p[t].r=n-y;
}
sort(p+1,p+t+1,cmp);
for(int i=1;i<=t;i++)
{
if(p[i].l!=p[i-1].l||p[i].r!=p[i-1].r)num++;
w[num]=min(w[num]+1,p[i].r-p[i].l+1);
L[num]=p[i].l;R[num]=p[i].r;
}
int j=1;
for(int i=1;i<=n;i++)
{
f[i]=f[i-1];
while(j<=num&&R[j]==i)
{
f[i]=max(f[i],f[L[j]-1]+w[j]);
j++;
}
}
cout<<n-f[n];
return 0;
}