agc015E - Mr.Aoki Incubator(dp)
题意
平面上有个点,每个点都有一个位置,和向右的速度
现在要求你对其中的一些点进行染色,当一个点被染色后,在无限距离内与它相遇的点也会被染色
问在可能的种染色方案中,有多少种染色方案可以使得最后的点全部被染色
Sol
非常好的dp题。
首先考虑若点被染色后,哪些点会被染色
最显然的两种情况
1. 且
2. 且
当然还有其他的情况,因为题目中的“染色”是一个连锁反应,也就是说被染色,又遇到了,那么也会被染色
实际上,当我们把所有点按速度从大到小排序。
对于,向左找到第一个的最小的(此时同时保证了最大)
向右找到第一个的最大的(同理保证了最小)
那么区间内所有的点都会被染色
现在问题转化成了,每个点能覆盖一段区间,问把区间覆盖的方案数
预处理出每个点能覆盖的区间。
这些区间有很多好的性质
满足
证明显然,拿l来说,对于按速度排序以后的排列中两个位置
若,此时
若,此时
右端点同理
注意一个细节,由于我们是按从大到小排序,这样处理起来不是很方便,直接把所有区间reverse一下
设表示用前个区间覆盖的方案
为其前缀和
前缀和优化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 + 7; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', 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 = 1; i <= N; i++) q.push_back(MP(a[i].x, a[i].id)); sort(q.begin(), q.end()); for(int i = 1; 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 = 1; 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 >= 1; 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 = 1; i <= N; i++) a[i].r = N - L[i] + 1, a[i].l = N - R[i] + 1; sort(a + 1, a + N + 1, 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 = 0; for(int i = 1, j = 1; i <= N; i++) { while(a[j].r < a[i].l - 1) j++; f[i] = (s[i - 1] + mod - s[j - 1] ) % mod; if(a[i].l == 1) f[i]++; if(a[i].r == N) (ans += f[i]) %= mod; s[i] = (s[i - 1] + f[i]) % mod; } return ans % mod; } main() { N = read(); for(int i = 1; i <= N; i++) a[i].x = read(), a[i].v = read(), a[i].id = i, date[i] = a[i].v; sort(date + 1, date + N + 1); int num = unique(date + 1, date + N + 1) - date - 1; for(int i = 1; i <= N; i++) a[i].v = lower_bound(date + 1, date + num + 1, a[i].v) - date; sort(a + 1, a + N + 1); GetL(L); GetR(R); //for(int i = 1; i <= N; i++) printf("%d %d\n", L[i], R[i]); printf("%d", dp() % mod); }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库