Description
一次考試共有n個人參加,第i個人說:“有ai個人分數比我高,bi個人分數比我低。”問最少有幾個人沒有說真話(可能有相同的分數)
題解
簡單DP。每個人有一個名詞區間,區間權值爲相同區間的個數,題目等價於選出一些不相交的線段,使權值最大。
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100006
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
int n,m,nn,f[maxn];
struct data{
int l,r,w;
bool operator <(const data&b)const{return r<b.r||(r==b.r&&l<b.l);}
}a[maxn],b[maxn];
void work(){
int i=1;
while(i<=m){
int j=i;
while(j<=m&&a[j].l==a[i].l&&a[j].r==a[i].r)j++;
b[++nn]=a[i];b[nn].w=min(j-i,a[i].r-a[i].l+1);
i=j;
}
}
int main(){
freopen("rank.in","r",stdin);
freopen("rank.out","w",stdout);
n=_read();
for(int i=1,x,y;i<=n;i++){
x=_read()+1;y=n-_read();
if(x>y)continue;
a[++m].l=x;a[m].r=y;
}
sort(a+1,a+1+m);work();int j=0;
for(int i=1;i<=nn;i++){
while(j<i&&b[j+1].r<b[i].l)j++;
f[i]=max(f[i-1],f[j]+b[i].w);
}
printf("%d\n",n-f[nn]);
return 0;
}