题意

题目链接

平面上有$n$个点,每个点都有一个位置$x_i$,和向右的速度$v_i$

现在要求你对其中的一些点进行染色,当一个点被染色后,在无限距离内与它相遇的点也会被染色

问在可能的$2^n$种染色方案中,有多少种染色方案可以使得最后的点全部被染色

Sol

非常好的dp题。

首先考虑若点$i$被染色后,哪些点会被染色

最显然的两种情况

1. $x_j < x_i$且$v_j > v_i$
2. $x_j > x_i$且$v_j < v_i$

当然还有其他的情况,因为题目中的“染色”是一个连锁反应,也就是说$a$被染色,$a$又遇到了$b$,那么$b$也会被染色

实际上,当我们把所有点按速度从大到小排序。

对于$x_i$,向左找到第一个$x_l < x_i$的最小的$l$(此时同时保证了$v_l$最大)
向右找到第一个$x_r > x_i$的最大的$r$(同理保证了$v_r$最小)

那么区间$[l, r]$内所有的点都会被染色

现在问题转化成了,每个点能覆盖一段区间$[l, r]$,问把区间$[l, N]$覆盖的方案数

预处理出每个点能覆盖的区间$[l, r]$。

这些区间有很多好的性质

满足$l_1 \leqslant l_2 \leqslant \dots \leqslant l_n, r_1 \leqslant r_2 \leqslant \dots \leqslant r_n$

证明显然,拿l来说,对于按速度排序以后的排列中两个位置$x_k, x_{k + 1}$

若$x_{k+1} < x_k$,此时$l_{k + 1} > l_k$
若$x_{k + 1} > x_k$,此时$l_{k + 1} = l_k$

右端点同理

注意一个细节,由于我们是按从大到小排序,这样处理起来不是很方便,直接把所有区间reverse一下

设$f[i]$表示用前$i$个区间覆盖$[1, n]$的方案

$s[i]$为其前缀和

前缀和优化dp即可

统计方案那里不是特别懂,路过的大佬可以说一下思路qwq

到了考场上还是写树状数组吧,无脑一点

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define fi first
#define se second
#define MP(x, y) make_pair(x, y)
#define LL long long
using namespace std;
const int MAXN = 1e6, mod = 1e9 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int N, date[MAXN], L[MAXN], R[MAXN], f[MAXN];
struct Node {
int x, v, id, l, r;
bool operator < (const Node &rhs) const {
return v > rhs.v;
}
}a[MAXN];
int comp(const Node &a, const Node &b) {
return a.r == b.r ? a.l < b.l : a.r < b.r;
}
void GetL(int *op) {
vector<Pair> q;
for(int i = ; i <= N; i++) q.push_back(MP(a[i].x, a[i].id));
sort(q.begin(), q.end());
for(int i = ; i <= N; i++) {
while(!q.empty()) {
if(a[i].x <= q.back().fi) op[q.back().se] = i, q.pop_back();
else break;
}
}
}
void GetR(int *op) {
vector<Pair> q;
for(int i = ; i <= N; i++) q.push_back(MP(a[i].x, a[i].id));
sort(q.begin(), q.end());
reverse(q.begin(), q.end());
for(int i = N; i >= ; i--) {
while(!q.empty()) {
if(a[i].x >= q.back().fi) op[q.back().se] = i, q.pop_back();
else break;
}
}
}
int dp() {
for(int i = ; i <= N; i++) a[i].r = N - L[i] + , a[i].l = N - R[i] + ;
sort(a + , a + N + , comp);
//for(int i = 1; i <= N; i++) printf("%d %d\n", a[i].l, a[i].r);
static int s[MAXN], f[MAXN];//f[i]:前i只猫覆盖所有区间的方案
int ans = ;
for(int i = , j = ; i <= N; i++) {
while(a[j].r < a[i].l - ) j++;
f[i] = (s[i - ] + mod - s[j - ] ) % mod;
if(a[i].l == ) f[i]++;
if(a[i].r == N) (ans += f[i]) %= mod;
s[i] = (s[i - ] + f[i]) % mod;
}
return ans % mod;
}
main() {
N = read();
for(int i = ; i <= N; i++) a[i].x = read(), a[i].v = read(), a[i].id = i, date[i] = a[i].v;
sort(date + , date + N + );
int num = unique(date + , date + N + ) - date - ;
for(int i = ; i <= N; i++) a[i].v = lower_bound(date + , date + num + , a[i].v) - date;
sort(a + , a + N + );
GetL(L); GetR(R);
//for(int i = 1; i <= N; i++) printf("%d %d\n", L[i], R[i]);
printf("%d", dp() % mod); }

agc015E - Mr.Aoki Incubator(dp)的更多相关文章

  1. 【AGC015E】Mr.Aoki Incubator DP

    题目描述 数轴上有\(n\)个人,每个人的位置是\(x_i\),速度是\(v_i\). 最开始有一些人感染了传染病. 如果某一时刻一个正常人和一个被感染的人处于同一位置,那么这个正常人也会被感染. 问 ...

  2. AGC015E Mr.Aoki Incubator

    atcoder luogu 首先可以考虑给一个人\(A\)染色.其他人被染色,要么被本来在后面的速度更快的人染色,要么被在前面的更慢的人染色.然后假设一个速度比最开始那个人慢的人\(B\)最后被染色了 ...

  3. AGC 015 E - Mr.Aoki Incubator

    E - Mr.Aoki Incubator 链接 题意: 数轴上有N个黑点,每个点都有一个方向向右的正速度v.当两个点在同一个位置上重合时,若其中一个是红色,另一个也变成红色.保证没有相同速度或初始坐 ...

  4. AtCoder Grand Contest 015 E - Mr.Aoki Incubator

    题目传送门:https://agc015.contest.atcoder.jp/tasks/agc015_e 题目大意: 数轴上有\(N\)个点,每个点初始时在位置\(X_i\),以\(V_i\)的速 ...

  5. 多校联训 DS 专题

    CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...

  6. AtCoder Grand Contest 015

    传送门 A - A+...+B Problem 题意:n个数最大值a,最小值b,求和的可能数量. #include<cstdio> #include<algorithm> us ...

  7. 【AtCoder】AGC015

    AGC015 A - A+...+B Problem #include <bits/stdc++.h> #define fi first #define se second #define ...

  8. 做题记录 To 2019.2.13

    2019-01-18 4543: [POI2014]Hotel加强版:长链剖分+树形dp. 3653: 谈笑风生:dfs序+主席树. POJ 3678 Katu Puzzle:2-sat问题,给n个变 ...

  9. AtCoder Grand Contest 015 题解

    A - A+...+B Problem 常识 Problem Statement Snuke has N integers. Among them, the smallest is A, and th ...

随机推荐

  1. new LayoutParams 使用

    ImageView imageView = new ImageView(mcontext); LayoutParams layoutParams = new LayoutParams(150,130) ...

  2. 关于startservice的几个启动返回值的意义

    START_NOT_STICKY 如果服务进程在它启动后(从onStartCommand()返回后)被kill掉, 并且没有新启动的intent传给他, 那么将服务移出启动状态并且不重新生成, 直到再 ...

  3. [51nod1212]最小生成树模板

    解题关键:注意下标 解法一:prim算法 #include<bits/stdc++.h> #define maxv 1002 #define maxm 50002 #define INF ...

  4. Jmeter连接MySQL配置(能执行多条sql语句)

    Database URL为MySQL的连接串,如果要执行多条SQL语句,后面还要添加“?allowMultiQueries=true”

  5. 学习过程的记录:实验室电脑上的jdk环境变量

    亲爱的,先区分安装路径和软件的存放路径好不好呢? 1.变量名:JAVA_HOME 变量值:D:\Program Files\Java\jdk1.7.0_21 2. 编辑 Path(粘贴到最后) %JA ...

  6. 26、HDF5 文件格式简介

    转载:庐州月光 http://www.cnblogs.com/xudongliang/p/6907733.html 三代测序下机的原始数据不再是fastq格式了,而是换成了hdf5 格式,在做三代数据 ...

  7. 存储引擎InnoDB

    InnoDB是MySQL的默认存储引擎, InnoDB支持的最大存储限制是64TB,支持事务安全,支持行锁,支持B树索引,不支持哈希索引和全文索引,支持集群索引,支持数据缓存,支持索引缓存,不支持数据 ...

  8. Umbraco中的RelatedLink的使用

    Umbraco中经常需要使用到RelatedLink, 那么在代码中我们如何来获取RelatedLink呢, 可能在Backoffice中我们有一个RelatedLink, 上面有3个链接,如下所示: ...

  9. Android Market google play store帐号注册方法流程 及发布应用注意事项

    Android Market google play store帐号申请 注册方法流程 在 Google Play 中发布软件之前,您需要完成以下三项工作: 创建开发人员个人资料 接受开发人员分发协议 ...

  10. C++基础之函数和作用域

    (1)函数的定义格式如下所示.<类型><函数名>(<形参表>) {<若干条语句>}其中,<类型>包含存储类和数据类型.存储类省略为外部函数, ...