[codeforces500E]New Year Domino
[codeforces500E]New Year Domino
试题描述
Celebrating the new year, many people post videos of falling dominoes; Here's a list of them: https://www.youtube.com/results?search_query=New+Years+Dominos
User ainta, who lives in a 2D world, is going to post a video as well.
There are n dominoes on a 2D Cartesian plane. i-th domino (1 ≤ i ≤ n) can be represented as a line segment which is parallel to the y-axis and whose length is li. The lower point of the domino is on the x-axis. Let's denote the x-coordinate of the i-th domino as pi. Dominoes are placed one after another, so p1 < p2 < ... < pn - 1 < pn holds.
User ainta wants to take a video of falling dominoes. To make dominoes fall, he can push a single domino to the right. Then, the domino will fall down drawing a circle-shaped orbit until the line segment totally overlaps with the x-axis.

Also, if the s-th domino touches the t-th domino while falling down, the t-th domino will also fall down towards the right, following the same procedure above. Domino s touches domino t if and only if the segment representing s and tintersects.

See the picture above. If he pushes the leftmost domino to the right, it falls down, touching dominoes (A), (B) and (C). As a result, dominoes (A), (B), (C) will also fall towards the right. However, domino (D) won't be affected by pushing the leftmost domino, but eventually it will fall because it is touched by domino (C) for the first time.

The picture above is an example of falling dominoes. Each red circle denotes a touch of two dominoes.
User ainta has q plans of posting the video. j-th of them starts with pushing the xj-th domino, and lasts until the yj-th domino falls. But sometimes, it could be impossible to achieve such plan, so he has to lengthen some dominoes. It costs one dollar to increase the length of a single domino by 1. User ainta wants to know, for each plan, the minimum cost needed to achieve it. Plans are processed independently, i. e. if domino's length is increased in some plan, it doesn't affect its length in other plans. Set of dominos that will fall except xj-th domino and yj-th domino doesn't matter, but the initial push should be on domino xj.
输入
The first line contains an integer n (2 ≤ n ≤ 2 × 105)— the number of dominoes.
Next n lines describe the dominoes. The i-th line (1 ≤ i ≤ n) contains two space-separated integers pi, li(1 ≤ pi, li ≤ 109)— the x-coordinate and the length of the i-th domino. It is guaranteed that p1 < p2 < ... < pn - 1 < pn.
The next line contains an integer q (1 ≤ q ≤ 2 × 105) — the number of plans.
Next q lines describe the plans. The j-th line (1 ≤ j ≤ q) contains two space-separated integers xj, yj (1 ≤ xj < yj ≤ n). It means the j-th plan is, to push the xj-th domino, and shoot a video until the yj-th domino falls.
输出
For each plan, print a line containing the minimum cost needed to achieve it. If no cost is needed, print 0.
输入示例
输出示例
数据规模及约定
见“输入”
题解
此外我们发现每个多米诺骨牌可以看做一个区间,若是这些区间有公共部分(或公共端点)就会导致这些区间对应的骨牌全部倒下。然后题目的询问就可以转换成区间内没有被覆盖的长度了。
这个问题当然可以用线段树做,但是下面有种 O(n + m) 的做法。
我们可以离线处理每个询问,把询问的左端点按照从大到小排序。这样就是从右往左依次添加区间了,在查询的时候我们需要知道对于一个位置 p,从它向右总共有多大的位置没有被覆盖(令它为 tot[p]),这样查询一个区间 [l, r] 的答案就是 tot[l] - tot[r]。
如何维护这个 tot 呢?
不妨令所有有公共部分的区间形成一个连通块,碰最左边的骨牌就会导致连通块中所有骨牌倒下。不难发现连通块中每一个位置的 tot 都是一样的;所以对于一个位置 p 我们就可以把这个 tot[p] 的值存到覆盖它的区间连通块的最靠左的位置上。想到什么了,没错,并查集!我们把每个连通块在并查集中对应的根设为最靠左的那个位置,那么我们只需要在每次左边插进来一个区间时,维护这个新的区间左端点的 tot 就好了,在查询任意位置 p 时,tot[p] = tot[findset(p)](findset() 就是并查集里的找根节点函数)。我们还需要一个栈来维护,在插入一个区间是,把栈中左端点小于等于新区间右端点的区间(即和当前区间有公共部分的区间)删掉(在删之前别忘了在并查集中把它的父亲设为新区间),最后再把这个新区间加到栈里就好了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 200010 struct Line {
int l, r;
Line() {}
Line(int _, int __): l(_), r(__) {}
} ls[maxn];
struct Que {
int l, r, id;
Que() {}
Que(int _1, int _2, int _3): l(_1), r(_2), id(_3) {}
bool operator < (const Que& t) const { return l < t.l; }
} qs[maxn];
int num[maxn<<1]; int fa[maxn], tot[maxn];
int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); } int S[maxn], top, ans[maxn]; int main() {
int n = read(), cntn = 0;
for(int i = 1; i <= n; i++) {
int l = read(), r = read() + l;
ls[i] = Line(l, r);
// printf("[%d, %d]\n", l, r);
}
int m = read();
for(int i = 1; i <= m; i++) {
int l = read(), r = read();
qs[i] = Que(l, r, i);
} for(int i = 1; i <= n; i++) fa[i] = i;
sort(qs + 1, qs + m + 1);
for(int i = m, j = n; i; i--) {
while(j && j >= qs[i].l) {
while(top && ls[S[top]].l <= ls[j].r) {
fa[findset(S[top])] = j;
ls[j].r = max(ls[j].r, ls[S[top]].r);
top--;
}
tot[j] = top ? tot[S[top]] + ls[S[top]].l - ls[j].r : 0;
S[++top] = j;
// for(int k = 1; k <= top; k++) printf("%d[%d,%d](%d)%c", S[k], ls[S[k]].l, ls[S[k]].r, tot[S[k]], k < top ? ' ' : '\n');
j--;
}
// printf("query: [%d, %d]\n", qs[i].l, qs[i].r);
int u = findset(qs[i].l), v = findset(qs[i].r);
ans[qs[i].id] = tot[u] - tot[v];
} for(int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0;
}
这题用线段树写起来舒服多了,虽然多个 log。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <bitset>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 400010 int n, q, num[maxn], A[maxn], cnt, ans[maxn];
struct Line {
int l, r, id;
Line() {}
Line(int _, int __): l(_), r(__) {}
Line(int _1, int _2, int _3): l(_1), r(_2), id(_3) {}
bool operator < (const Line& t) const { return l > t.l; }
} ls[maxn], qs[maxn]; int sumv[maxn<<2];
bool setv[maxn<<2];
void build(int o, int l, int r) {
if(l == r) sumv[o] = A[l];
else {
int mid = l + r >> 1, lc = o << 1, rc = lc | 1;
build(lc, l, mid); build(rc, mid + 1, r);
sumv[o] = sumv[lc] + sumv[rc];
}
return ;
}
void pushdown(int o, int l, int r) {
if(!setv[o]) return ;
if(l == r){ setv[o] = 0; return ; }
int lc = o << 1, rc = lc | 1;
setv[lc] = setv[rc] = 1;
sumv[lc] = sumv[rc] = 0;
return ;
}
void update(int o, int l, int r, int ql, int qr) {
pushdown(o, l, r);
if(ql <= l && r <= qr) {
sumv[o] = 0; setv[o] = 1;
return ;
}
int mid = l + r >> 1, lc = o << 1, rc = lc | 1;
if(ql <= mid) update(lc, l, mid, ql, qr);
if(qr > mid) update(rc, mid + 1, r, ql, qr);
sumv[o] = sumv[lc] + sumv[rc];
return ;
}
int query(int o, int l, int r, int ql, int qr) {
pushdown(o, l, r);
if(ql <= l && r <= qr) return sumv[o];
int mid = l + r >> 1, lc = o << 1, rc = lc | 1, ans = 0;
if(ql <= mid) ans += query(lc, l, mid, ql, qr);
if(qr > mid) ans += query(rc, mid + 1, r, ql, qr);
return ans;
} int main() {
n = read();
for(int i = 1; i <= n; i++) {
int l = read(), r = l + read();
num[++cnt] = l; num[++cnt] = r;
ls[i] = Line(l, r);
}
sort(num + 1, num + cnt + 1);
cnt = unique(num + 1, num + cnt + 1) - num - 1; for(int i = 1; i < cnt; i++) A[i] = num[i+1] - num[i];
for(int i = 1; i <= n; i++) {
int &l = ls[i].l, &r = ls[i].r;
l = lower_bound(num + 1, num + cnt + 1, l) - num;
r = lower_bound(num + 1, num + cnt + 1, r) - num - 1;
}
int q = read();
for(int i = 1; i <= q; i++) {
int l = read(), r = read();
qs[i] = Line(l, r, i);
}
sort(qs + 1, qs + q + 1);
build(1, 1, cnt - 1);
for(int i = 1, j = n; i <= q; i++) {
while(j && j >= qs[i].l) update(1, 1, cnt - 1, ls[j].l, ls[j].r), j--;
ans[qs[i].id] = query(1, 1, cnt - 1, ls[qs[i].l].l, ls[qs[i].r].l);
} for(int i = 1; i <= q; i++) printf("%d\n", ans[i]); return 0;
}
[codeforces500E]New Year Domino的更多相关文章
- BPM Domino集成解决方案
一.需求分析 Lotus Notes/Domino是IBM的协同办公平台,在国内有广泛的用户. 但由于推出年头较早.采用文档数据库等特点, 导致其流程集成能力弱.统计分析难.不支持移动办公等问题,很多 ...
- 【转载】给那些想多学习,多进步的Domino初学者
在这个社区里面,包括QQ技术群里面混了很久了.遇到了很多Domino初学者,也认识了很多致力于Domino这个技术领域的朋友,很开心.很久没有写长篇大论给大家了.我要把一些想法写出来,共大家参考.讨论 ...
- FineReport中Domino数据库连接方法
1. 概述 Domino是文档型数据库而非关系型数据库,连接Domino可以使用JDBC方式或者ODBC方式,使用JDBC方式需要安装Lotus Domino Driver for JDBC并且此方法 ...
- IBM Domino 9 出现 Server Controller 未在主机上运行或未在端口2050监听 解决方案
如果在网上搜索的方法,比如防火墙开端口还没有解决的话,那么我的解决方案可能会解决你的问题. 出现的场景: 我先装了Notes,Designer,后装Domino Server, 配置Domino服务器 ...
- CF 405B Domino Effect(想法题)
题目链接: 传送门 Domino Effect time limit per test:1 second memory limit per test:256 megabytes Descrip ...
- [ACM_图论] Domino Effect (POJ1135 Dijkstra算法 SSSP 单源最短路算法 中等 模板)
Description Did you know that you can use domino bones for other things besides playing Dominoes? Ta ...
- 如何开发Domino中的WebService
在domino中写webservice可以使用LotusScript,也可以使用java,由于LotusScript API提供的功能多数都是操作domino数据库中文档的,在web service中 ...
- 结合Domino打造全功能的Grid
1. 需求说明: 在domino开发中我们经常会遇到表单上需要一个类似table的组件,你可以增删改等.比如我有一个张报核单据,上面需要详细列出每项金额的明细,我们先看完成后的效果: 上面 ...
- 关于Domino数据库的软删除
在Domino的数据库属性的 “高级” 附签(选择文件->数据库->属性),选中“允许软删除”,这样我们就启用了软删除功能,当一个文档没有删除的时候我们可以使用NotesDatabase的 ...
随机推荐
- Windowsforms 中 进程,线程
进程: 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动. 它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体. Process 类,用来操作进程. 命名空间:using Syst ...
- 一个DBA萌新的烦恼
莫名其妙也好机缘巧合也罢,现在我成为了一名MySQL DBA. 为什么: 1.为什么leader让我转到DBA? 首先,我本身学习运维管理的时候就接触过数据库(mysql,redis),算是自身的优势 ...
- MYSQL5.7 忘记ROOT密码/初始化ROOT密码
编辑my.cnf允许空密码登录 [root@7Core ~]# vi /etc/my.cnf #在[mysqld]下加入一行 skip-grant-tables=1 重新启动Mysql服务 [root ...
- CF919D Substring
思路: 拓扑排序过程中dp.若图有环,返回-1. 实现: #include <bits/stdc++.h> using namespace std; ; vector<int> ...
- 前端css3样式前缀自动补全工具--autoprefixer
最近在学习一份来自git的动画框架源码,看懂70%的核心代码后,打算自己动手实践一版,然鹅,所有框架搭起来以后,在动画这块却出了问题: 想设计一个slideInLeft的动画,必然想到了要从偏移-10 ...
- 在SQLServer 2005附加SQLServer 2008数据库异常处理
远程服务器软件系统不算新,数据库是SQL Server 2005.本地开发基本是用新的软件系统.数据库采用SQL Server 2008. 这样在用远程服务器SQL 2005选择附加SQL 2008的 ...
- GIS在石油行业中的应用
在石油工业中,发现新的石油资源,取得竞争优势,是成功的关键之一.GIS系统能帮助评估潜在的石油资源,及时.准确.直观地定位油气资源的空间分布及其特征,以正确有效地开展部署勘探开发工作,占领市场先机. ...
- 用yunio网盘搭建git私有仓库
研究生开始奔波于教研室和寝室之间,于是想搭建一个git私有仓库来管理自己在做的项目或者学习资料.一来可以很方便的管理项目,二来可以学习使用git.我的主要工作平台是Linux,这也是我选择yuni ...
- yii在Windows下安装(通过composer方式)
Composer 安装: (Composer 不是一个包管理器,它仅仅是一个依赖管理工具.它涉及 "packages" 和 "libraries",但它在每个项 ...
- Activiti数据库表结构(表详细版)
http://blog.csdn.net/hj7jay/article/details/51302829 1 Activiti数据库表结构 1.1 数据库表名说明 Activiti工作流总 ...