谁在说谎

谁在说谎

链接:https://ac.nowcoder.com/acm/contest/1168/H 来源:牛客网

邓志聪是一位非常聪明的小伙子,这次他在某个学校当班主任,他班上有n个学生,然而有些学生非常的讨厌邓志聪。一次考试结束后,邓志聪想知道这些学生的考试情况,于是一个一个叫这些学生叫去办公室问他们,但是有些学生并没有讲真话,第i个学生说:“有ai个人分数比我高,bi个人分数比我低。”邓志聪想知道最少有几个学生没有说真话,你能帮助他吗?(可能有相同的分数)

输入描述:

第一行一个整数n,接下来每行两个整数,第i+1行两个整数代表ai,bi。(1<=n<=100000,0<=ai,bi<=n)

输出描述:

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

示例1

输入

3
1 1
2 2
0 2

输出

1
思路:

最少有几个学生没有说真话,反过来就是最多有多少个学生说的是真话。通过给出的每组数据\(a{_i}、b{_i}\)可以得出一个区间\([L,R]\),这个区间内的所有学生排名相同 。这个区间里的学生最多有\(L-R+1\)个学生,记录这个区间出现的次数,就是说真话的学生个数。最后用DP得出整个区间最大的人数。

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 100005;
const int inf = 0x3f3f3f3f;
const int M = 1e9+7;
int n,m;
std::map<pair<int,int>, int> mp;
std::vector<int> p[maxn];
int dp[maxn];

int main()
{
    int n,l,r;
    cin>>n;
    for(int i = 0,x,y; i < n; i++)
    {
        cin>>x>>y;
        l = x+1;
        r = n-y;
        if(l > r) continue;
        //if(r-l+1 > mp[make_pair(l,r)])
        mp[make_pair(l,r)]++;   //记录区间出现次数
        if(mp[make_pair(l,r)] == 1) p[r].push_back(l); //记录以r为右边界的的区间
    }
    //dp[i]表示以i为右边界的区间的最大人数
    for(int i = 1; i <= n; i++)  
    {
        dp[i] = dp[i-1];
        for(auto j : p[i])
        {
            dp[i] = max(dp[i],dp[j-1]+min(mp[make_pair(j,i)],i-j+1)); 
        }//mp[make_pair(j,i)可能大于区间最大容量,当大于的时候直接取i-j+1
    }
    cout<<n-dp[n]<<endl;
    return 0;
}
posted @ 2019-11-24 21:33  chilkings  阅读(201)  评论(0编辑  收藏  举报