题意:

从左到右排列着\(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. display:none和visibility:hidden v-show和v-if的区别

    隐藏元素display:none 和 visibility:hidden的区别visibility:hidden可以隐藏某个元素,但是隐藏的元素仍要占据空间,仍要影响布局display:none不会占 ...

  2. Spring Cloud--搭建Eureka注册中心服务

    使用RestTemplate远程调用服务的弊端: Eureka注册中心: Eureka原理: 搭建Eureka服务 引pom 启动类: 启动类上要加上@EnableEurekaServer注解: 配置 ...

  3. es6+字符串string的新增方法函数

    String.includes("xxx")   返回true/false     [es5的字符串查找方法:String.indexOf() ] String.startsWit ...

  4. Outlook 0x800CCC1A 错误

    使用POP3帐户时,您可能在Outlook 2013/2016中看到以下错误.我在Exchange Server 2013环境中遇到此问题,在Windows 8.1上运行的Microsoft Outl ...

  5. Python3+Selenium3+webdriver学习笔记11(cookie处理)

    #!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记11(cookie处理)'''from selenium im ...

  6. Lodash.js常用拷贝

    lodash.js 降低 array.number.objects.string 等等的使用难度从而让 JavaScript 变得更简单.非常适用于:遍历 array.object 和 string: ...

  7. Android(java)学习笔记118:BroadcastReceiver之 外拨电话的广播接收者

    1. 外拨电话的广播接收者: 首先我们示例工程一览表如下: (2)首先我们还是买一个收音机,定义一个OutCallReceiver继承自BroadcastReceiver,onReceive()方法中 ...

  8. 使用MaskedTextBox控件实现输入验证

    实现效果: 知识运用: MaskedTextBox控件的 Mask属性 BeepOnError属性 MaskInputRejected事件 实现代码: private void Form1_Load( ...

  9. MVC和MVP到底有什么区别呢?

    MVC和MVP到底有什么区别呢?   MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写 MVP 全称:Model-V ...

  10. PAT (Basic Level) Practise (中文)- 1007. 素数对猜想 (20)

    http://www.patest.cn/contests/pat-b-practise/1007 让我们定义 dn 为:dn = pn+1 - pn,其中 pi 是第i个素数.显然有 d1=1 且对 ...