题意:

从左到右排列着\(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. java命令--jstack 工具

    一.介绍 jstack是java虚拟机自带的一种堆栈跟踪工具.jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项&qu ...

  2. Array.isArray() 和 isObject() 原生js实现

    function isObject(val) { return val != null && typeof val === 'object' && Array.isAr ...

  3. Java实现多线程下载 URL以及URLConnection

    主线程: public class MultiThreadDown { public static void main(String[] args) throws Exception{ //初始化Do ...

  4. Java Object Model(一)

    Java作为OOP语言,抽象性不言而喻.如果需要深入了解Java语言的实现机制,则不得不对Java语言中基础的概念有清晰的了解.今天是我在cnblog上写博客的第一天,希望今天的博客可以是我成为未来& ...

  5. ERROR 2013 (HY000): Lost connection to MySQL server at 'reading authorization packet', system error: 0

    最近遇到一个MySQL连接的问题,远程连接MySQL时遇到"ERROR 2013 (HY000): Lost connection to MySQL server at 'reading a ...

  6. Windows Azure 配置Active Directory 主机(1)

    现在越来越多企业将自己业务系统迁移云端,方便公司日常运维管理.这篇文章将简单介绍一下,从 Windows Azure 虚拟网络上的虚拟机 (VM) 中的 Corp Active Directory 林 ...

  7. LR脚本中常用函数使用介绍

    1.变量和参数的设置 //将IP地址和端口放入到参数中lr_save_string("192.168.1.133:8081","ip"); //计算变量数组的元 ...

  8. BZOJ 1396:识别子串 SA+树状数组+单调队列

    1396: 识别子串 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 381  Solved: 243[Submit][Status][Discuss] ...

  9. ansible-galera集群部署

    一.环境准备 1.各主机配置静态域名解析: [root@node1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain local ...

  10. JQuery EasyUI学习记录(四)

    1.EasyUI中的validatebox使用 提供的校验规则: 1.非空校验required="required" 2.使用validType指定 email: 正则表达式匹配电 ...