H的范围是10^15,DP方程很容易想到。但是因为H的范围太大了,而n的范围还算可以接受。因此,对高度排序排重后。使用新的索引建立线段树,使用线段树查询当前高度区间内的最大值,以及该最大值的前趋索引。线段树中的结点索引一定满足i<j的条件,因为采用从n向1更新线段树结点。每次线段树查询操作就可以得到argmax(dp[L, R]),很据不等式很容易得到L和R的范围。
1 /* 474E */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <algorithm> 10 #include <cstdio> 11 #include <cmath> 12 #include <ctime> 13 #include <cstring> 14 #include <climits> 15 #include <cctype> 16 using namespace std; 17 18 #define lson l, mid, rt<<1 19 #define rson mid+1, r, rt<<1|1 20 21 typedef struct { 22 __int64 mx; 23 int fa; 24 } node_t; 25 26 const int maxn = 1e5+5; 27 node_t nd[maxn<<2]; 28 __int64 h[maxn], hh[maxn]; 29 int fa[maxn], dp[maxn]; 30 31 void PushUp(int rt) { 32 int lb = rt<<1; 33 int rb = rt<<1|1; 34 35 if (nd[lb].mx >= nd[rb].mx) { 36 nd[rt].fa = nd[lb].fa; 37 nd[rt].mx = nd[lb].mx; 38 } else { 39 nd[rt].fa = nd[rb].fa; 40 nd[rt].mx = nd[rb].mx; 41 } 42 } 43 44 void build(int l, int r, int rt) { 45 nd[rt].mx = -1; 46 nd[rt].fa = 0; 47 if (l == r) 48 return ; 49 int mid = (l+r)>>1; 50 build(lson); 51 build(rson); 52 } 53 54 void update(int x, int in, int l, int r, int rt) { 55 if (l == r) { 56 if (nd[rt].mx < dp[in]) { 57 nd[rt].mx = dp[in]; 58 nd[rt].fa = in; 59 } 60 return ; 61 } 62 int mid = (l+r)>>1; 63 if (x <= mid) 64 update(x, in, lson); 65 else 66 update(x, in, rson); 67 PushUp(rt); 68 } 69 70 node_t query(int L, int R, int l, int r, int rt) { 71 node_t d; 72 if (L<=l && R>=r) 73 return nd[rt]; 74 int mid = (l+r)>>1; 75 if (R <= mid) { 76 return query(L, R, lson); 77 } else if (L > mid) { 78 return query(L, R, rson); 79 } else { 80 node_t ln = query(L, R, lson); 81 node_t rn = query(L, R, rson); 82 return rn.mx>ln.mx ? rn:ln; 83 } 84 } 85 86 int main() { 87 int i, j, k; 88 int n, m, d; 89 int ans, v; 90 int l, r; 91 node_t node; 92 __int64 tmp; 93 94 #ifndef ONLINE_JUDGE 95 freopen("data.in", "r", stdin); 96 freopen("data.out", "w", stdout); 97 #endif 98 99 scanf("%d %d", &n, &d); 100 for (i=1; i<=n; ++i) { 101 scanf("%I64d", &h[i]); 102 hh[i] = h[i]; 103 } 104 sort(h+1, h+1+n); 105 m = unique(h+1, h+1+n) - (h+1); 106 build(1, m, 1); 107 108 for (i=n; i>0; --i) { 109 dp[i] = 1; 110 fa[i] = 0; 111 112 tmp = hh[i] + d; 113 if (tmp <= h[m]) { 114 l = lower_bound(h+1, h+1+m, tmp) - h; 115 node = query(l, m, 1, m, 1); 116 if (node.mx+1 > dp[i]) { 117 dp[i] = node.mx + 1; 118 fa[i] = node.fa; 119 } 120 } 121 122 tmp = hh[i] - d; 123 if (tmp >= h[1]) { 124 r = m+1; 125 if (tmp < h[m]) 126 r = upper_bound(h+1, h+1+m, tmp) - h; 127 node = query(1, r-1, 1, m, 1); 128 if (node.mx+1 > dp[i]) { 129 dp[i] = node.mx + 1; 130 fa[i] = node.fa; 131 } 132 } 133 134 l = lower_bound(h+1, h+1+m, hh[i]) - h; 135 update(l, i, 1, m, 1); 136 } 137 138 ans = dp[1]; 139 v = 1; 140 for (i=2; i<=n; ++i) { 141 if (dp[i] > ans) { 142 ans = dp[i]; 143 v = i; 144 } 145 } 146 147 printf("%d\n", ans); 148 printf("%d", v); 149 while (fa[v]) { 150 v = fa[v]; 151 printf(" %d", v); 152 } 153 putchar(‘\n‘); 154 155 #ifndef ONLINE_JUDGE 156 printf("%d\n", (int)clock()); 157 #endif 158 159 return 0; 160 }
时间: 2024-12-29 12:48:56