[CEOI2018] Lottery 题解
前言
题目链接:洛谷。
题意简述
给出序列
每次询问一个
题目分析
暴力不用说,考虑如何优化。这类问题我们思考能不能省略重复的计算。例如,对于
具体地讲,对于这两个区间,它们的差值的可能性是
另外,由于特殊的空间限制,不妨将询问离线并离散化,空间复杂度就降到了
代码
略去了快读快写。
#include <cstdio> #include <algorithm> using namespace std; int n, m, q, val[10010]; int cnt[110][10010]; int qry[110], rq[110], who[10010]; signed main() { fread(buf, 1, MAX, stdin); read(n), read(m); for (int i = 1; i <= n; ++i) read(val[i]); read(q); for (int i = 1; i <= q; ++i) read(qry[i]), rq[i] = qry[i]; sort(rq + 1, rq + q + 1); for (int i = 1; i <= q; ++i) who[rq[i]] = i; who[m + 1] = q + 1; for (int i = m; i >= 0; --i) !who[i] && (who[i] = who[i + 1]); for (int i = 1; i + m <= n; ++i) { // 两个区间的差 int tot = 0; for (int j = 1; j <= m; ++j) tot += val[j] != val[j + i]; for (int l1 = 1, r1 = m, l2 = 1 + i, r2 = m + i; r2 <= n; ++l1, ++l2, ++r1, ++r2) { ++cnt[who[tot]][l1], ++cnt[who[tot]][l2]; tot -= val[l1] != val[l2]; tot += val[r1 + 1] != val[r2 + 1]; } } for (int i = 1; i <= q; ++i) for (int j = 1; j + m - 1 <= n; ++j) cnt[i][j] += cnt[i - 1][j]; for (int i = 1; i <= q; ++i) { for (int j = 1; j + m - 1 <= n; ++j) write(cnt[who[qry[i]]][j]), putchar(' '); putchar('\n'); } fwrite(obuf, 1, o - obuf, stdout); return 0; }
后记 & 反思
考虑重复计算并优化是关键。另外,枚举两个区间的位置关系,并做到不重不漏的统计也是值得注意的。
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18316425。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】