【题目大意】

有$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的更多相关文章

  1. 「6月雅礼集训 2017 Day8」route

    [题目大意] 给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串. $n \leq 5000$ [题解] 考虑取凸包上一点,然后如果下一个是‘R' ...

  2. 「6月雅礼集训 2017 Day8」gcd

    [题目大意] 定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤. 那么有: 1. times(a, b) = times(b, a) 2. times(a, 0) = 0 3. ...

  3. 「6月雅礼集训 2017 Day10」quote

    [题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...

  4. 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...

  5. 「6月雅礼集训 2017 Day11」delight

    [题目大意] 有$n$天,每天能吃饭.睡觉.什么事也不干 每天吃饭的愉悦值为$e_i$,睡觉的愉悦值为$s_i$,什么都不干愉悦值为0. 要求每连续$k$天都要有至少$E$天吃饭,$S$天睡觉. 求最 ...

  6. 「6月雅礼集训 2017 Day11」jump

    [题目大意] 有$n$个位置,每个位置有一个数$x_i$,代表从$i$经过1步可以到达的点在$[\max(1, i-x_i), \min(i+x_i, n)]$中. 定义$(i,j)$的距离表示从$i ...

  7. 「6月雅礼集训 2017 Day11」tree

    [题目大意] 给出一棵带权树,有两类点,一类黑点,一类白点. 求切断黑点和白点间路径的最小代价. $n \leq 10^5$ [题解] 直接最小割能过..但是树形dp明显更好写 设$f_{x,0/1/ ...

  8. 「6月雅礼集训 2017 Day10」perm(CodeForces 698F)

    [题目大意] 给出一个$n$个数的序列$\{a_n\}$,其中有些地方的数为0,要求你把这个序列填成一个1到$n$的排列,使得: $(a_i, a_j) = 1$,当且仅当$(i, j) = 1$.多 ...

  9. 「6月雅礼集训 2017 Day7」电报

    [题目大意] 有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价. $1 \leq n \leq 10^5, 1 ...

随机推荐

  1. Web服务器性能压力测试工具

    一.http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载. 但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般 ...

  2. 高性能python

    参考来源:Python金融大数据分析第八章 提高性能有如下方法 1.Cython,用于合并python和c语言静态编译泛型 2.IPython.parallel,用于在本地或者集群上并行执行代码 3. ...

  3. MATLAN中矩阵表示中有一维是~表示的意思

    [~,m]表示的意思解释. [~,m]=rat(12/34) m = 17 >> [x,m]=rat(12/34) x = 6 m = 17

  4. [洛谷P4430]小猴打架

    题目大意:有$n$个点,问有多少种连成生成树的方案. 题解:根据$prufer$序列可得,$n$个点的生成树有$n^{n-2}$个,每种生成树有$(n-1)!$种生成方案,所以答案是$n^{n-2}( ...

  5. BZOJ2555:SubString——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2555 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作 ...

  6. 虚拟机网络连接模式中桥接模式和NAT模式的区别

    1.桥接模式:当虚拟机系统的网络连接模式为桥接模式时,相当于在主机系统和虚拟机系统之间连接了一个网桥,而网桥两端的网络都属于同一网络,主机和虚拟机是处于同一网络中的对等主机. 实例,在使用Xshell ...

  7. 洛谷 P2024 [NOI2001]食物链 解题报告

    P2024 [NOI2001]食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个 ...

  8. P2075 [NOIP2012T5]借教室 区间更新+二分查找

    P2075 [NOIP2012T5]借教室 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 noip2012-tg 描述 在大学期间,经常需要租借教室.大到院 ...

  9. Codeforces Round #345 (Div. 2) A

    A. Joysticks time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  10. mysql的时间函数整理

      转:这里总结的非常齐全: http://fengbin2005.iteye.com/blog/1999763   Mysql时间函数 对于每个类型拥有的值范围以及并且指定日期何时间值的有效格式的描 ...