「6月雅礼集训 2017 Day8」infection
【题目大意】
有$n$个人,每个人有一个初始位置$x_i$和一个速度$v_i$,你需要选择若干个人来感染一个傻逼病毒。
当两个人相遇(可以是正面和背面),傻逼病毒会传染,求经过无限大时间后,传染完所有人的方案数。
【题解】
考虑经过无限大时间后结束的数列,一定是按$v_i$排序的。
对于第i个人,如果他带有病毒,那么
原来在它左边的速度最大的点一定会超过它,到达右边能到达的最大值,这个点会经过若干个点,这些都会被传染。
原来在它右边的速度最小的点一定会跑到它的后面,到达左边能到达的最小值,同理也会被传染。
所以每个人的传染是最后的一个区间,这个区间可以用线段树或者单调队列找出,然后就是经典的区间覆盖问题了。
有一种非常美妙的$O(n)$的dp可以解决这个问题。
反正xjb做就可以了,具体看代码
# include <vector>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int M = 2e5 + ;
const int inf = 1.05e9;
const int mod = 1e9 + ; int n;
struct pa {
int x, v, ps;
pa() {}
pa(int x, int v, int ps) : x(x), v(v), ps(ps) {}
}p[M]; inline bool cmp_pos(pa a, pa b) {
return a.x < b.x;
}
inline bool cmp_va(pa a, pa b) {
return a.v < b.v;
} struct segnode {
int w, id;
segnode() {}
segnode(int w, int id) : w(w), id(id) {}
friend bool operator < (segnode a, segnode b) {
return a.w < b.w;
}
friend bool operator > (segnode a, segnode b) {
return a.w > b.w;
}
}; struct SMT {
# define ls (x<<)
# define rs (x<<|)
segnode mx[M << ], mi[M << ];
inline void set() {
for (int i=; i<=(n<<); ++i) mx[i] = segnode(-inf, -);
for (int i=; i<=(n<<); ++i) mi[i] = segnode(inf, -);
}
inline void edt(int x, int l, int r, int ps, int d, int dd) {
if(l == r) {
mx[x] = mi[x] = segnode(d, dd);
return ;
}
int mid = l+r >> ;
if(ps <= mid) edt(ls, l, mid, ps, d, dd);
else edt(rs, mid+, r, ps, d, dd);
mi[x] = min(mi[ls], mi[rs]);
mx[x] = max(mx[ls], mx[rs]);
}
inline segnode gmin(int x, int l, int r, int L, int R) {
if(L > R) return segnode(inf, -);
if(L <= l && r <= R) return mi[x];
int mid = l+r>>;
segnode ret = segnode(inf, -);
if(L <= mid) ret = min(ret, gmin(ls, l, mid, L, R));
if(R > mid) ret = min(ret, gmin(rs, mid+, r, L, R));
return ret;
}
inline segnode gmax(int x, int l, int r, int L, int R) {
if(L > R) return segnode(-inf, -);
if(L <= l && r <= R) return mx[x];
int mid = l+r>>;
segnode ret = segnode(-inf, -);
if(L <= mid) ret = max(ret, gmax(ls, l, mid, L, R));
if(R > mid) ret = max(ret, gmax(rs, mid+, r, L, R));
return ret;
}
}T; int pos[M];
int f[M], s[M]; struct intervals {
int l, r;
intervals() {}
intervals(int l, int r) : l(l), r(r) {}
friend bool operator < (intervals a, intervals b) {
return a.r < b.r || (a.r == b.r && a.l < b.l);
}
}a[M]; int main() {
// freopen("infection.in", "r", stdin);
// freopen("infection.out", "w", stdout);
cin >> n;
for (int i=; i<=n; ++i) scanf("%d%d", &p[i].x, &p[i].v);
sort(p+, p+n+, cmp_pos);
for (int i=; i<=n; ++i) p[i].ps = i;
sort(p+, p+n+, cmp_va);
for (int i=; i<=n; ++i) T.edt(, , n, p[i].ps, p[i].v, i);
// for (int i=1; i<=n; ++i) printf("pos = %d, value = %d, x = %d, id = %d\n", p[i].ps, p[i].v, p[i].x, i);
for (int i=; i<=n; ++i) {
a[i].r = T.gmax(, , n, , p[i].ps-).id;
if(a[i].r == -) a[i].r = i;
a[i].l = T.gmin(, , n, p[i].ps+, n).id;
if(a[i].l == -) a[i].l = i;
a[i].l = min(a[i].l, i);
a[i].r = max(a[i].r, i);
// printf("%d %d\n", a[i].l, a[i].r);
} sort(a+, a+n+); f[] = s[] = ;
for (int i=, j=; i<=n; ++i) {
s[i] = s[i-];
for (; j<=n && a[j].r == i; ++j) {
// printf("%d %d %d\n", i, a[j].r, s[a[j].r]);
int tem = s[a[j].r] - ((a[j].l == ) ? : s[a[j].l-]);
if(tem < ) tem += mod;
f[i] += tem; if(f[i] >= mod) f[i] -= mod;
s[i] = s[i-] + f[i]; if(s[i] >= mod) s[i] -= mod;
}
} cout << f[n] << endl;
return ;
}
「6月雅礼集训 2017 Day8」infection的更多相关文章
- 「6月雅礼集训 2017 Day8」route
[题目大意] 给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串. $n \leq 5000$ [题解] 考虑取凸包上一点,然后如果下一个是‘R' ...
- 「6月雅礼集训 2017 Day8」gcd
[题目大意] 定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤. 那么有: 1. times(a, b) = times(b, a) 2. times(a, 0) = 0 3. ...
- 「6月雅礼集训 2017 Day10」quote
[题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...
- 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)
原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...
- 「6月雅礼集训 2017 Day11」delight
[题目大意] 有$n$天,每天能吃饭.睡觉.什么事也不干 每天吃饭的愉悦值为$e_i$,睡觉的愉悦值为$s_i$,什么都不干愉悦值为0. 要求每连续$k$天都要有至少$E$天吃饭,$S$天睡觉. 求最 ...
- 「6月雅礼集训 2017 Day11」jump
[题目大意] 有$n$个位置,每个位置有一个数$x_i$,代表从$i$经过1步可以到达的点在$[\max(1, i-x_i), \min(i+x_i, n)]$中. 定义$(i,j)$的距离表示从$i ...
- 「6月雅礼集训 2017 Day11」tree
[题目大意] 给出一棵带权树,有两类点,一类黑点,一类白点. 求切断黑点和白点间路径的最小代价. $n \leq 10^5$ [题解] 直接最小割能过..但是树形dp明显更好写 设$f_{x,0/1/ ...
- 「6月雅礼集训 2017 Day10」perm(CodeForces 698F)
[题目大意] 给出一个$n$个数的序列$\{a_n\}$,其中有些地方的数为0,要求你把这个序列填成一个1到$n$的排列,使得: $(a_i, a_j) = 1$,当且仅当$(i, j) = 1$.多 ...
- 「6月雅礼集训 2017 Day7」电报
[题目大意] 有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价. $1 \leq n \leq 10^5, 1 ...
随机推荐
- NIO初探
NIO的前世今生 NIO又叫NonBlockingI/O,即非阻塞I/O.以此对应的,有一个更常见的IO(BIO),又叫Blocking I/O,即阻塞IO,两种都为Java的IO实现方案. NIO/ ...
- Java中I/O流之处理流类型
节点流:一个管道直接连接到数据源上面: 处理流:套在别的管道上面的管道: 处理流类型: [注]:在字符流中的OuPutStreamReader写错了,应该是:OutputStreamWriter
- 数据库索引(结合B-树和B+树)
数据库索引,是数据库管理系统中一个排序的数据结构以协助快速查询.更新数据库表中数据.索引的实现通常使用B树及其变种B+树. 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种 ...
- PowerMock用法[转]
转:http://agiledon.github.io/blog/2013/11/21/play-trick-with-powermock/ 当我们面对一个遗留系统时,常见的问题是没有测试.正如Mic ...
- C运行时库
原文地址:http://blog.csdn.net/wqvbjhc/article/details/6612099 在开发window程序是经常会遇到编译好好的程序拿到另一台机器上面无法运行的情况,这 ...
- HSF原理
HSF(High-speed Service Framework),高速服务框架,是阿里系主要采用的服务框架,其目的是作为桥梁联通不同的业务系统,解耦系统之间的实现依赖.其高速体现在底层的非阻塞I/O ...
- asp.net mvc4中Json的应用
做一个简单的 Json实例,从页面获取后台的Json数据 1.控制台: public class HomeController : Controller { // // GET: /Home/ pub ...
- Lucene笔记二
lucene 的排序 package cn.itcast.lucene; import java.io.IOException; import org.apache.lucene.document.D ...
- nargchk函数 matlab【转】
功能说明 验证输入参数的个数 函数语法 msgstring = nargchk(minargs, maxargs, numargs)msgstring = nargchk(minargs, max ...
- SVG总结小知识
SVG:可缩放矢量图形.全称是:Scalable Vector Graphics SVG使用 XML 格式定义图像. SVG是使用 XML 来描述(二维图形和绘图)程序的语言. SVG是W3C ...