"SCOI2014" Fang Bobo cornfield

Dynamic programming + data structure optimization

Every time the right point greater operating range bound for n, because to try to get behind the numbers

Note F [i] [k] for the i-th to corn ending the total length of the longest operation sequence does not fall times k

Since each operation is a right end point n, the left point is less than equal to i

So in this case i is a height h [i] + k

则 f[i][k] = max(f[j][l]) + 1 // h[j] + l <= h[i] + k, j < i, l <= k

Each state f [i] [k] can be expressed as (k, h [i] + k) // number of operations, the end of the height

Taking each transition corresponds to (K, H) K <= k, H [i] + maximum value <= h k of

You can use a two-dimensional array to maintain the tree

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 1e4 + 5, K = 505, H = 6005;
 5 
 6 int n, k, h[N], Max, f[N][K], tr[K][H], ans;
 7 
 8 int query(int x, int y) {
 9     int i = x, res = 0;
10     while (i) {
11         int j = y;
12         while (j) {
13             res = max(res, tr[i][j]);
14             j -= (j & (-j));
15         }
16         i -= (i & (-i));
17     }
18     return res;
19 }
20 
21 void update(int x, int y, int val) {
22     int i = x;
23     while (i <= k + 1) {
24         int j = y;
25         while (j <= Max) {
26             tr[i][j] = max(tr[i][j], val);
27             j += (j & (-j));
28         }
29         i += (i & (-i));
30     }
31     return;
32 }
33 
34 int main() {
35     cin >> n >> k;
36     for (int i = 1; i <= n; i++) {
37         scanf("%d", &h[i]);
38         Max = max(Max, h[i] + k);
39     }
40     for (int i = 1; i <= n; i++)
41         for (int j = k; j >= 0; j--) {
42             f[i][j] = query(j + 1, h[i] + j) + 1;
43             ans = max(ans, f[i][j]);
44             update(j + 1, h[i] + j, f[i][j]);
45         }
46     cout << ans << endl;
47 }

 

Guess you like

Origin www.cnblogs.com/ympc2005/p/12318290.html