1109: [POI2007]堆积木Klo

1109: [POI2007]堆积木Klo

https://lydsy.com/JudgeOnline/problem.php?id=1109

分析:

  首先是dp,f[i]表示到第i个的最优值,f[i]=f[j]+1,(j<i,a[j]<a[i],j-a[j]<i-a[i]),三维偏序,可以cdq+线段树转移。实际上由a[j]<a[i]和j-a[j]<i-a[i]可以推出j<i所以二维偏序,直接LIS。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13  
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18  
19 const int N = 1000005;
20  
21 struct Node{
22     int x, c;
23     bool operator < (const Node &A) const {
24         return x == A.x ? c > A.c : x < A.x;
25     } 
26 }A[N]; 
27 int f[N];
28  
29 int main() {
30     int n = read(), cnt = 0;
31     for (int i = 1; i <= n; ++i) {
32         int x = read();
33         if (i - x >= 0) 
34         A[++cnt].x = x, A[cnt].c = i - x;
35     }
36     if (cnt == 0) {
37         cout << 0; return 0;
38     }
39     int len = 1;
40     sort(A + 1, A + cnt + 1);
41     f[1] = A[1].c;
42     for (int i = 2; i <= cnt; ++i) {
43         if (A[i].x != A[i - 1].x && A[i].c >= f[len]) f[++len] = A[i].c;
44         else {
45             int p = upper_bound(f + 1, f + len + 1, A[i].c) - f;
46             f[p] = A[i].c;
47         }
48     }
49     cout << len;
50     return 0;
51 }
52 
LIS
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13  
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18  
19 const int N = 1000005;
20  
21 struct Node{
22     int id, x, c;
23     bool operator < (const Node &A) const {
24         return c == A.c ? x < A.x : c < A.c;
25     } 
26 }A[N], B[N]; 
27 int f[N], mx;
28  
29 #define Root 1, mx, 1
30 #define lson l, mid, rt << 1
31 #define rson mid + 1, r, rt << 1 | 1
32 struct SegmentTree{
33     int mx[N << 2];
34     SegmentTree() { for (int i = 0; i <= 4000000; ++i) mx[i] = -1e9; }
35     void update(int l,int r,int rt,int p,int v) {
36         if (l == r) { mx[rt] = v; return ; }
37         int mid = (l + r) >> 1;
38         if (p <= mid) update(lson, p, v);
39         else update(rson, p, v);
40         mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
41     }
42     int query(int l,int r,int rt,int p) {
43         if (p < 1) return -1e9;
44         if (r <= p) return mx[rt];
45         int mid = (l + r) >> 1;
46         if (p <= mid) return query(lson, p);
47         else return max(mx[rt << 1], query(rson, p));
48     }
49 }T;
50  
51 void cdq(int l,int r) {
52     if (l >= r) return ;
53     int mid = (l + r) >> 1;
54     cdq(l, mid);
55     for (int i = mid + 1; i <= r; ++i) B[i] = A[i];
56     sort(B + mid + 1, B + r + 1);
57     for (int p = l, j = mid + 1; j <= r; ++j) {
58         if (f[B[j].id] == -1e9) continue;
59         while (p <= mid && A[p].c <= B[j].c) T.update(Root, A[p].x, f[A[p].id]), p ++;
60         f[B[j].id] = max(f[B[j].id], T.query(Root, B[j].x - 1) + 1);    
61     }
62     for (int i = l; i <= mid; ++i) T.update(Root, A[i].x, 0); // B[i].x!!! 
63     cdq(mid + 1, r);
64     sort(A + l, A + r + 1);
65 }
66  
67 int main() {
68     int n = read();
69     for (int i = 1; i <= n; ++i) {
70         A[i].x = read(), A[i].id = i, A[i].c = i - A[i].x;
71         if (A[i].x <= i) f[i] = 1;
72         else f[i] = -1e9;
73         mx = max(mx, A[i].x);
74     }
75     cdq(1, n);
76     int ans = 0;
77     for (int i = 1; i <= n; ++i) ans = max(ans, f[i]);
78     cout << ans;
79     return 0;
80 }
81 
CDQ

 

posted @ 2018-11-30 10:25  MJT12044  阅读(170)  评论(0编辑  收藏  举报