标签:
先把所有人从小到大排序,则
如果一个人说a个人比他大,b个人比他小,等价于他声称[b + 1, n - a]的值是相等的
问题转化为给一些线段,找出一些不重叠的线段,价值最大 (注意:线段可以重合!!!)
然后就是一遍扫过去的DP
f[i]表示以线段i为结尾的满足条件的线段最多数
f[i] = max(f[j]) + cnt[i], 其中r[j] < l[i], cnt[i]表示i这条线段重合次数
DP要优化的说,不过只要二分一下嘛就好了!
1 /************************************************************** 2 Problem: 2298 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:792 ms 7 Memory:5012 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 #include <utility> 13 #include <map> 14 15 using namespace std; 16 typedef pair<int, int> P; 17 const int N = 100005; 18 struct data{ 19 int x, y, cnt; 20 bool f; 21 }a[N]; 22 inline bool operator < (const data a, const data b){ 23 return a.y == b.y ? a.x < b.x : a.y < b.y; 24 } 25 map <P, int> M; 26 int n, f[N], X, Y, l; 27 28 inline int read(){ 29 int x = 0, sgn = 1; 30 char ch = getchar(); 31 while (ch < ‘0‘ || ch > ‘9‘){ 32 if (ch == ‘-‘) sgn = -1; 33 ch = getchar(); 34 } 35 while (ch >= ‘0‘ && ch <= ‘9‘){ 36 x = x * 10 + ch - ‘0‘; 37 ch = getchar(); 38 } 39 return sgn * x; 40 } 41 42 int main(){ 43 n = read(); 44 for (int i = 1; i <= n; ++i){ 45 X = read(), Y = read(); 46 a[i].f = (X + Y >= n); 47 a[i].x = n - X, a[i].y = ++Y; 48 if (a[i].x > a[i].y) swap(a[i].x, a[i].y); 49 a[i].cnt = min(M[make_pair(a[i].x, a[i].y)] += a[i].f ^ 1, a[i].y - a[i].x + 1); 50 } 51 sort(a + 1, a + n + 1); 52 for (int i = 1; i <= n; ++i){ 53 if (a[i].f){ 54 f[i] = f[i - 1]; 55 continue; 56 } 57 l = lower_bound(a + 1, a + i, (data){-1, a[i].x}) - a - 1; 58 f[i] = max(f[i - 1], f[l] + a[i].cnt); 59 } 60 printf("%d\n", n - f[n]); 61 return 0; 62 }
标签:
原文地址:http://www.cnblogs.com/rausen/p/4345380.html