【CF】474E Pillars

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 }

 

posted on 2015-04-13 20:40  Bombe  阅读(317)  评论(0编辑  收藏  举报

导航