• [HAOI2011][BZOJ2298] problem a


    2298: [HAOI2011]problem a

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 766  Solved: 346
    [Submit][Status][Discuss]

    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

    首先,要求最少说谎人数,即最大说真话人数。

    对于每一个人,有a[i]个比他分数高的,b[i]个比他分数低的。则若序列为单调不增序列,和他同分的人的序号一定在a[i]+1->n-b[i]之间。因此可以想象成一段线段,问题转化为在一个长度为n的线段上有几段线段,求几段不想交的线段的长度之和,使这个值最大。

    于是就是一个dp的题目了。方程显而易见。

    又了解了一个map,在黄学长题解里还看到了动态数组?自己STL好弱……过几天系统学一下。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    using namespace std;
    map <pair<int,int>,int> s;
    int a,b,n,m,dp[100001],head[100001],next[100001],list[100001];
    void add(int x,int y)
    {
        next[++m]=head[x];
        head[x]=m;
        list[m]=y;
    }
    int main()
    {
        scanf("%d",&n);
        m=0;
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            if (a+b>=n) continue;
            a++;
            b=n-b;
            if (!s[make_pair(a,b)]) add(b,a);
            s[make_pair(a,b)]=min(s[make_pair(a,b)]+1,b-a+1);
        }
        for (int i=1;i<=n;i++)
        {
            dp[i]=dp[i-1];
            for (int j=head[i];j;j=next[j])
            {
                int u=list[j]-1;
                dp[i]=max(dp[i],dp[u]+s[make_pair(u+1,i)]);
            }
        }
        printf("%d",n-dp[n]);
        return 0;
    }
  • 相关阅读:
    POJ 3009
    POJ 3253
    POJ 3617
    POJ 3984
    UVA10012
    HDU5100
    HDU 5101
    UVA301 运输
    UVA 331 交换的方案数
    uva 10344 算23点
  • 原文地址:https://www.cnblogs.com/ws-fqk/p/4643921.html
Copyright © 2020-2023  润新知