【康复训练】【DP】【BZOJ】2298: [HAOI2011]problem a

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;
}

猜你喜欢

转载自blog.csdn.net/fyoier/article/details/80385790