先把所有人从小到大排序,则

如果一个人说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 }
View Code

 

posted on 2015-03-17 19:41  Xs酱~  阅读(711)  评论(0编辑  收藏  举报