P3514题解
给一个只有1和2的序列,每次询问有没有一个子串的和为x
SPJ对于格式的要求较为严格。对于每个询问后,应紧跟一个换行符。在最后一次输出你的答案以及一个换行符后不应有任何输出。
由zhouyonglong提供SPJ
题解
首先因为元素只能为1/2,所以我们可以思考如何利用上这个性质,可以发现如下重要性质
若存在一个和为
证明:设这个区间为
那么我们就可以考虑将一个足够大的区间往回缩,不断递归,可以得到与此区间的和的奇偶性相同且小于的所有值所对区间
到了这里,做法就很显然了,先找到最大奇数段和最大偶数段,然后递归预处理每个值的答案区间即可,复杂度只有
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 2000050
#define scanf scanf_s
struct node {
int l, r;
}ans[N];
int val[N], n, m, q, s1[N], s2[N], pos1, pos2;
void dfs(int l, int r, int k) {
if (ans[k].l)return;
if (l > r)return;
ans[k] = { l,r };
if (val[l] == 2) {
dfs(l + 1, r, k - 2);
}
else if (val[r] == 2) {
dfs(l, r - 1, k - 2);
}
else dfs(l + 1, r - 1, k - 2);
}
void init() {
memset(ans, 0, sizeof ans);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
char x;
cin >> x;
if (x == 'T')val[i] = 2;
else val[i] = 1;
}
for (int i = 1; i <= n; i++)s1[i] = s1[i - 1] + val[i];
for (int i = n; i >= 1; --i)s2[i] = s2[i + 1] + val[i];
for (int i = 1; i <= n; i++)if (val[i] == 1) { pos1 = i + 1; break; }
for (int i = n; i > 0; --i)if (val[i] == 1) { pos2 = i - 1; break; }
if (s2[pos1] > s1[pos2]) { dfs(pos1, n, s2[pos1]); }
else { dfs(1, pos2, s1[pos2]); }
dfs(1, n, s1[n]);
}
int main() {
init();
while (m--) {
int k;
scanf("%d", &k);
if (ans[k].l == 0)puts("NIE");
else printf("%d %d\n", ans[k].l, ans[k].r);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!