【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 }
时间: 2024-08-18 19:36:18

【CF】474E Pillars的相关文章

【CF】38E Let&#39;s Go Rolling! (dp)

前言 这题还是有点意思的. 题意: 给你 \(n\) (\(n<=3000\)) 个弹珠,它们位于数轴上.给你弹珠的坐标 \(x_i\) 在弹珠 \(i\) 上面花费 \(C_i\) 的钱 可以使弹珠在原地不动 (\(-10^9<=x_i,C_i<=10^9\)),游戏开始时,所有的弹珠向左滚动,直到碰到定在原地不动的弹珠,其花费是其滚动的距离.总花费=开始前的花费+弹珠滚动的花费,问最小的花费是多少 题解 首先划分出阶段,,我们可以先将弹珠排序,前 \(i\) 个弹珠,最后一个固定的弹

【CF】codeforces round 369(div2)

*明早起来再贴代码 A [题意] 给定n*5的方格 将横向的相邻两个变成+输出   [题解] ...   B [题意] 一个n*n的正整数矩阵,有且仅有一个数为0 ,在这个位置填上一个数,使得每一列的和 每一行的和 两条对角线各自的和都相等 输出这个数   [题解]sb题.暴力一下.注意细节,否则你就像这样 (不是本人   C [题意] 一排点,用1~n表示,熊孩子要给这些点上色.最初每个点的颜色为ci.一共有m种颜色,如果ci=0表示这个点最初无色. 熊孩子们需要给最初为无色的点涂上色,往第i

【CF】Codeforces Round #361 (Div. 2)

难得有想法写一整套题解 首先想说的是,这场CF,我感觉是div2极为不错的一场(对于中档选手<因为我就出了三题,还掉了一个-- 说笑了,感觉这一场很耐人寻味.就是那种抓破头皮想不出,知道做法后细细品味,有种   哦~~~~~这样啊~~~~好神奇!!! 的感觉 首先..秀一下战绩 不多说了 都在题里 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ A. Mike and Cellphone time limit per test 1 second memory limit per test 256 megaby

【CF】掉分总结

比赛总结 前情提要 自从前段时间连续掉分,就心态崩了,还是自己太菜,一直想写个总结,看看这几场比赛都干了啥,以后准备怎么办.鸽了这么久的总结,是该写写了. 这是正文 首先大致提一下情感曲线(菜的真实): 那一晚,那一夜,sc大佬突然qq发消息给我,"打cf吗",我眉头一紧,这个cf莫非是穿越火线?又一想大佬才不会玩这种游戏,又一想,难道是codeforces?我颤颤巍巍的回了"codeforces?",大佬回的很快,扔给我了个链接,并说"这是616,你做吧

【CF】121 Div.1 C. Fools and Roads

题意是给定一棵树.同时,给定如下k个查询: 给出任意两点u,v,对u到v的路径所经过的边进行加计数. k个查询后,分别输出各边的计数之和. 思路利用LCA,对cnt[u]++, cnt[v]++,并对cnt[LCA(u, v)] -= 2.然后dfs求解各边的计数. 1 /* 191C */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #inc

【CF】207 Div.1 B.Xenia and Hamming

这题目一看很牛逼,其实非常easy.求求最小公倍数,最大公约数,均摊复杂度其实就是O(n). 1 /* 356B */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <dequ

【CF】283D Tennis Game

枚举t加二分判断当前t是否可行,同时求出s.注意不能说|a[n]| <= |3-a[n]|就证明无解,开始就是wa在这儿了.可以简单想象成每当a[n]赢的时候,两人都打的难解难分(仅多赢一轮):而每当a[n]输的时候,一轮都没赢.在这个前提下,显然存在|a[n]| <= |3-a[n]|. 1 /* 283D */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include &l

【CF】196 Div.2 Book of Evil

显然这个图是一课树,看着题目首先联想到LCA(肯定是可以解的).但是看了一下数据大小,应该会TLE.然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径.结果灵感就来了,主要思路是对于每个结点,第一次dfs得到两个变量到P结点的最大值以及次大值.然后,第二次dfs对于当前结点u,u到它的子树中P类结点的最大距离已知(nd[u].mx),那么除u的其他结点v到P类结点的最大距离加上v到u的距离和的最大值为pmx,可以通过每次深搜计算出来,只要d大于等于两者的最大值

【CF】3B Lorry

这道题目网上有几个题解,均有问题.其实就是简单的贪心+排序,没必要做的那么复杂.一旦tot+curv > v时,显然curv==2, 有三种可能:(1)取出最小的curv==1的pp,装入当前的p:(2)取出后续最大的curv==1的p,并且装入:(3)当前已经是最优的(即后续不存在curv==1的类型),同时前一个的pp比当前的p更优.(这种情况不需要特判) 1 /* 3B */ 2 #include <iostream> 3 #include <string> 4 #in