「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 ...
随机推荐
- Delegate(QLabel和QComboBox)
一.最终效果 二.实现思路 1.createEditor()中create两个控件,分别是QLabel和QComboBox,将其添加到一个widget中,然后返回该widget: 2.setEdito ...
- 进程间通信:命名管道FIFO(2)
一.命名管道 如果我们想在不相关的进程之间交换数据,可以用FIFO文件来完成这项工作,它通常也被称为命名管道.命名管道是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和我们已经见 ...
- iOS-AFNetworking与ASIHTTPRequest的区别
一.底层实现 1.AFN的底层实现基于OC的NSURLConnection和NSURLSession 2.ASI的底层实现基于纯C语言的CFNetwork框架 3.因为NSURLConnectio ...
- 转 linux安装swoole扩展
linux安装swoole扩展 发表于2年前(2014-09-03 14:05) 阅读(4404) | 评论(3) 7人收藏此文章, 我要收藏 赞2 上海源创会5月15日与你相约[玫瑰里],赶快来 ...
- 解决连接mysql报错1130
最近在服务器上部署好的应用突然间连接不上mysql数据库,报错“ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this M ...
- 9.1、AutoEncoder自动编码器[转]
如果给定一个神经网络,我们假设其输出与输入是相同的,然后训练调整其参数,得到每一层中的权重.自然地,我们就得到了输入I的几种不同表示(每一层代表一种表示),这些表示就是特征.自动编码器就是一种尽可能复 ...
- Java中的缓冲流详解
缓冲流增强了读写文件的能力,比如Student.txt是一个学生的名单,每个姓名占一行.如果我们想要读取名字,那么每次必须读取一行,使用FileReader流很难完成这样的任务,因为我们不清楚一行有多 ...
- 锁-lock,信号量4
1. 全局解释器锁,保证同一时间只有一个线程在执行,但是由于它是把数据copy成了两份,所以 只有全局解释器锁的时候,数据加减照样出错了. 2.用户态的锁,保证同一时间,只有一个线程在真真正正地修改数 ...
- 洛谷3690:【模板】Link Cut Tree——题解
https://www.luogu.org/problemnew/show/P3690 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- Educational Codeforces Round 39 (Rated for Div. 2) G
Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...