谁在说谎
谁在说谎
链接: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;
}