【康復訓練】【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;
}
發佈了143 篇原創文章 · 獲贊 18 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章