bzoj 2298: [HAOI2011]problem a

2298: [HAOI2011]problem a

Description

一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)

Input

第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi

Output

一个整数,表示最少有几个人说谎

Sample Input

3
2 0
0 2
2 2

Sample Output

1

HINT

100%的数据满足: 1≤n≤100000   0≤ai、bi≤n

ACTY真大神!!!

——————————以下题解————————————

输入n个x,y,即表示有x个人分数比i高,y个人分数比i低,那么有n-x-y个人分数和i一样

我们把i看作一个序列中的第x+1个人,前面的人都比他大,x+1~n-y之间的人分数和他一样

那么题目可以转化为给出n条线段,从中能挑出的最多的互不重叠的线段数即为最多的正确人数

至于这么求有很多方法,我还是喜欢DP。。。。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
    int a,b;
}p[100005];
int n,i,j,k,s,x,y,a[100005],h[100005],l[100005],r[100005],f[100005];
bool cmp(const node&x,const node&y)
{
    if(x.b!=y.b) return x.b<y.b;
    return x.a<y.a;
}
int main()
{
    scanf("%d",&n);
    k=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        if(x+y>=n) continue;
        k++;
        p[k].a=x+1;
        p[k].b=n-y;
    }
    sort(p+1,p+k+1,cmp);
    s=0;
    for(i=1;i<=k;i++)
    {
        if(p[i].a!=p[i-1].a||p[i].b!=p[i-1].b) s++;
        h[s]++;
        h[s]=min(h[s],p[i].b-p[i].a+1);
        l[s]=p[i].a;
        r[s]=p[i].b;
    }
    j=1;
    for(i=1;i<=n;i++)
    {
        f[i]=f[i-1];
        while(j<=s&&r[j]==i)
        {
            f[i]=max(f[i],f[l[j]-1]+h[j]);
            j++;
        }
    }
    cout<<n-f[n];
    return 0;
}

 

posted @ 2016-05-10 20:56  lwq12138  阅读(464)  评论(2编辑  收藏  举报