[BZOJ2298] problem a
Description
一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)
Input
第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi
Output
一个整数,表示最少有几个人说谎
Sample Input
3
2 0
0 2
2 2
2 0
0 2
2 2
Sample Output
1
HINT
100%的数据满足: 1≤n≤100000 0≤ai、bi≤n
好吧...其实讲完了我还是不会。
抄的题解2333...
设f[i]表示前i个人最多有多少个人说的是真话。
然后f[i] = max(f[j-1] + sum[j, i]),sum是指排名可能的区间为[l,r]的人的个数。
然后这样转移是O(N^2)的。
但是有不少冗余状态,也就是说,sum[i, j]=0,为结局我这种情况我们可以对每一个r建立一个vector存储对应这个r的l。
然后怎么如果硬开空间的话空间复杂度也是O(N^2)的承受不了, 所以可以用map;
#include <iostream> #include <cstdio> #include <map> #include <vector> using namespace std; inline int read() { int res=0;char c=getchar();bool f=0; while(!isdigit(c)) {if(c=='-')f=1;c=getchar();} while(isdigit(c))res=(res<<3)+(res<<1)+(c^48),c=getchar(); return f?-res:res; } int n; int f[100005]; map < pair <int, int>, int > sum; vector <int> p[100005]; int main() { n = read(); for (register int i = 1 ; i <= n ; i ++) { int l = read() + 1, r = n - read(); if (l > r) continue; sum[make_pair(l, r)]++; if (sum[make_pair(l, r)] == 1) p[r].push_back(l); } for (register int i = 1 ; i <= n ; i ++) { f[i] = f[i-1]; for (register int j = 0 ; j < p[i].size() ; j ++) f[i] = max(f[i], f[p[i][j]-1] + min(sum[make_pair(p[i][j], i)], i - p[i][j] + 1)); } printf("%d\n", n - f[n]); return 0; }