题意:

从左到右排列着\(n\)个多米诺骨牌,它们分别站在\(x\)轴上的位置\(p_i\)上且高度为\(l_i\)。

当第\(i\)个多米诺骨牌向右倒下时,如果\(p_i < p_j \leq p_i + l_i\)那么第\(j\)个多米诺骨牌也会倒下,以此类推。

然后有\(q\)个询问\([x, \, y]\),要推倒第\(x\)个多米诺骨牌,而且最终要使得第\(y\)个多米诺骨牌倒下。

为了使第\(y\)个倒下,可以加长某些牌的长度。

对于每个询问,求最少加长的总长度之和。

分析:

对于第\(i\)个牌,定义\(R_i\)为推倒第\(i\)个牌,所倒下的牌中\(p_j+l_j\)的最大值。

有递推式:\(R_i=max \{ p_i+l_i, \, max\{ R_j | p_i < p_j \leq p_i+l_i \} \}\)

\(R_i\)可以通过维护线段树计算得到。

接下来根据\(R_i\)计算\(U_i\),表示推倒第\(i\)个牌后,最左边没有倒下的牌的编号。

因此从\(x\)到\(U_x\),我们至少需要增加\(p_{U_{x}} - R_x\)的长度。

所以我们向右一步一步地加,直到第\(y\)块倒下为止。

但是这样每次查询的复杂度为\(O(n)\)的。

所以还需要二进制优化一下,类似于求\(LCA\)的倍增算法。

\(anc(i, \, j)\)表示迭代\(2^j\)次\(U_i\)最后得到的牌的编号,\(cost(i, \, j)\)表示相应增加的牌的长度。

\(O(nlogn)\)预处理一下,就可以做到\(O(logn)\)查询。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 200000 + 10; int n, q;
int p[maxn], l[maxn];
int R[maxn], U[maxn]; int maxv[maxn << 2]; void update(int o, int L, int R, int p, int v) {
if(L == R) { maxv[o] = v; return; }
int M = (L + R) / 2;
if(p <= M) update(o<<1, L, M, p, v);
else update(o<<1|1, M+1, R, p, v);
maxv[o] = max(maxv[o<<1], maxv[o<<1|1]);
} int query(int o, int L, int R, int qL, int qR) {
if(qL <= L && R <= qR) { return maxv[o]; }
int M = (L + R) / 2;
int ans = 0;
if(qL <= M) ans = max(ans, query(o<<1, L, M, qL, qR));
if(qR > M) ans = max(ans, query(o<<1|1, M+1, R, qL, qR));
return ans;
} int anc[maxn][20], cost[maxn][20]; int lb(int l, int r, int x) {
while(l < r) {
int mid = (l + r) / 2 + 1;
if(p[mid] <= x) l = mid;
else r = mid - 1;
}
return l;
} int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d%d", p + i, l + i);
for(int i = n; i; i--) {
R[i] = p[i] + l[i];
int lft = i + 1;
int rgh = lb(1, n, p[i] + l[i]);
if(lft <= rgh) R[i] = max(R[i], query(1, 1, n, lft, rgh));
update(1, 1, n, i, R[i]);
}
for(int i = 1; i <= n; i++) {
U[i] = upper_bound(p + 1, p + 1 + n, R[i]) - p;
if(U[i] == n + 1) U[i]--;
} for(int i = 1; i <= n; i++) {
anc[i][0] = U[i];
cost[i][0] = max(0, p[U[i]] - R[i]);
}
for(int j = 1; (1 << j) < n; j++)
for(int i = 1; i <= n; i++) if(anc[i][j-1] != n) {
int t = anc[i][j-1];
anc[i][j] = anc[t][j-1];
cost[i][j] = cost[i][j-1] + cost[t][j-1];
} scanf("%d", &q);
while(q--) {
int x, y; scanf("%d%d", &x, &y);
int ans = 0;
for(int i = 19; i >= 0; i--) if(anc[x][i] && anc[x][i] <= y) {
ans += cost[x][i];
x = anc[x][i];
}
if(x < y) ans += max(0, p[y] - p[U[x]]);
printf("%d\n", ans);
} return 0;
}

CodeForces 500E New Year Domino的更多相关文章

  1. 【codeforces 500E】New Year Domino

    [题目链接]:http://codeforces.com/problemset/problem/500/E [题意] 有n个多米诺骨牌; 你知道它们的长度; 然后问你,如果把第i骨牌往后推倒,然后要求 ...

  2. Codeforces 238 div2 B. Domino Effect

    题目链接:http://codeforces.com/contest/405/problem/B 解题报告:一排n个的多米诺骨牌,规定,若从一边推的话多米诺骨牌会一直倒,但是如果从两个方向同时往中间推 ...

  3. 【CodeForces 353 A】Domino

    [链接] 我是链接,点我呀:) [题意] [题解] 分类讨论一波 设第一个数组的奇数个数为cnt1 第二个数组的奇数个数为cnt2 显然只有在(cnt1+cnt2)%2==0的情况下. 才可能第一个数 ...

  4. CF数据结构练习

    1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...

  5. Codeforces Good Bye 2015 C. New Year and Domino 前缀和

    C. New Year and Domino 题目连接: http://www.codeforces.com/contest/611/problem/C Description They say &q ...

  6. CodeForces - 50A Domino piling (贪心+递归)

    CodeForces - 50A Domino piling (贪心+递归) 题意分析 奇数*偶数=偶数,如果两个都为奇数,最小的奇数-1递归求解,知道两个数都为1,返回0. 代码 #include ...

  7. Codeforces 500 E. New Year Domino

    \(>Codeforces \space 500 E. New Year Domino<\) 题目大意 : 数轴上有序排列着 \(n\) 块多米诺骨牌, 第 \(i\) 块骨牌坐标为 \( ...

  8. Codeforces Round #609 (Div. 2) D. Domino for Young

    链接: https://codeforces.com/contest/1269/problem/D 题意: You are given a Young diagram. Given diagram i ...

  9. Codeforces Round #588 (Div. 2) C. Anadi and Domino(思维)

    链接: https://codeforces.com/contest/1230/problem/C 题意: Anadi has a set of dominoes. Every domino has ...

随机推荐

  1. AJPFX关于JDK,JRE,JVM的区别与联系

    很多朋友可能跟我一样,对JDK,JRE,JVM这三者的联系与区别,一直都是模模糊糊的. 今天我们来整理下三者的关系. JDK : Java Development ToolKit(Java开发工具包) ...

  2. 有关在python中使用Redis(二)

    这里简单介绍下在python中使用如何使用hashset,set和list: 从list开始: 一般我们使用lpush对一个list进行初始化添加,但是如果需要不断往这个list里面加值,就要用rpu ...

  3. LoadRunner创建脚本和场景流程

    1)脚本创建流程创建脚本->选择协议-设置录制选项-录制脚本-停止录制-优化脚本(去掉无用内容)-强化脚本(注释.代码结构调整.参数化.检查点.事物.关联)-调试脚本(观察日志) 2)场景设置的 ...

  4. github上fork原项目,如何将本地仓库代码更新到最新版本?

    场景: 在github上fork原项目,项目组成员发起pull request提交了代码,这时自己在本地仓库该如何更新到最新代码? 操作方法如下: 方法一.从github上进行操作然后更新 登录自己的 ...

  5. 拷贝文件至U盘——提示:对于目标系统文件过大

    一.问题描述: 在制作U盘启动工具的时候,通常制作出的U盘文件系统是FAT32,但是当需要拷贝进去的系统文件大小超过4GB时,就会提示上述问题 二.解决办法: 1.格式化U盘,在格式化界面“文件系统” ...

  6. 两个div并列居中显示——当display:inline-block;时,两个div无法对齐即一高一矮

    解决办法: 给div添加样式vertical-align: top;

  7. webpack安装包的时候 1程序目录不要在C盘 2路径不要有中文 3用cnpm

    webpack安装包的时候 1程序目录不要在C盘 2路径不要有中文 3用cnpm

  8. Kubernetes之pod的属性

    属性名称 取值类型                   是否必选 取值说明 version String Required(必) 版本号,例如v1 kind String Required pod m ...

  9. 重新postgresql出现错误:Problem running post-install step. Installation may not complete correctly. The database cluster initialisation failed.

    以前正常使用的postgresql,今天出现问题:报*.dll错误.百度了一下,只能重新安装 . 在重新安装过程中报:Problem running post-install step. Instal ...

  10. CPP-STL:vector中的size和capacity

    在vector中与size()和capacity() 相对应的有两个函数: resize(size_type)和reserve(size_type). Size指目前容器中实际有多少元素,对应的res ...