最少多少人说谎(dp)
https://ac.nowcoder.com/acm/contest/1168/H
题意:n个学生,邓志聪想知道这些学生的考试情况,于是一个一个叫这些学生叫去办公室问他们,但是有些学生并没有讲真话,第i个学生说:“有ai个人分数比我高,bi个人分数比我低。”邓志聪想知道最少有几个学生没有说真话,你能帮助他吗?(可能有相同的分数)
解法:逆向思维求最多有多少人没说谎,用区间代表该名同学所处的位置,区间值代表该区间人数。
dp求解不重叠区间值之和最大即可。
//#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f #define mod 20191117 #define PI acos(-1) using namespace std; typedef long long ll ; map<pair<int , int > , int>m; vector<int>ans[100100]; int dp[100100]; int main() { int n ; scanf("%d" , &n); for(int i = 0 ; i < n ; i++) { int x , y ; scanf("%d%d" , &x , &y); int l = x + 1 ;//高的在左 int r = n - y ;//低的在右 if(l > r) continue; if(m[make_pair(l , r)] < r - l + 1) m[make_pair(l , r)]++;//区间值代表人数 if(m[make_pair(l , r)] == 1) ans[r].push_back(l); } for(int i = 1 ; i <= n ; i++) { dp[i] = dp[i -1];//i为右边界。 for(auto j : ans[i])//ans[i]中第二维中的元素的左边界 { dp[i] = max(dp[i] , dp[j-1] + m[make_pair(j , i)]); } } cout << n - dp[n] << endl ; return 0; }