P6006 [USACO20JAN]Farmer John Solves 3SUM G 题解
善良的出题人已经在题面中告诉你了:
尚未发现运行速度比平方时间明显更优的解法。
而 O(qn2) 过不了,所以题目显然是让你以 O(n2) 进行预处理,再进行 O(1) 查询。
思考在暴力 O(n3) 处理时,我们是以三元组 (i,j,k) 进行三重循环,逐个检查是否 si+sj+sk=0。不妨对这个式子进行变换,可得 sk=−si−sj。这时利用桶统计 [i,j] 中的 −si−sj 数量即可。
在面对 q 次询问时,考虑 用 vi,j 表示区间 [i,j] 中的结果。则有 vi+1,j 为区间 (i,j] 中的结果, vi,j−1 为区间 [i,j) 中的结果, vi+1,j−1 为区间 (i,j) 中的结果。易得:
vi,j=vi+1,j+vi,j−1−vi+1,j−1+fi,j
可惜的是这会导致你 MLE。应该把数组 v 去掉,因为 f 就可以了:
fi,j=fi+1,j+fi,j−1−fi+1,j−1
本题代码细节较恶心,故意跟数组过不去,应格外注意:
-
查找 −si−sj 时要加上常数 M,因为数组不能访问负的,会数组越界。
-
M应该在 106 以上,这是由于你后面要 −si−sj,开的过小容易加后还是负数。
-
桶应该开为 2×M,如果较小可能会因为 +M 而数组越界。
View code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ri register int
#define il inline
const int N=5010,M=2e6+10;
int n,Q;
int s[N],b[M<<1];
ll f[N][N];
il ll read(){
ll x=0,y=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
y=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*y;
}
il void work(){
for(ri i=1;i<=n;i++){
for(ri j=i+1;j<=n;j++){
f[i][j]=b[M-s[i]-s[j]];
b[s[j]+M]++;
}
for(ri j=i+1;j<=n;j++)
b[s[j]+M]=0;
}
for(ri i=3;i<=n;i++){
for(ri j=1;j<=n-i+1;j++){
int k=i+j-1;
f[j][k]+=f[j+1][k]+f[j][k-1]-f[j+1][k-1];
}
}
}
signed main(){
n=read(),Q=read();
for(ri i=1;i<=n;i++)
s[i]=read();
work();
while(Q--){
int a=read(),b=read();
printf("%lld\n",f[a][b]);
}
return 0;
}
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从“看懂世界”到“改造世界”:AI发展的四个阶段你了解了吗?
· 协程本质是函数加状态机——零基础深入浅出 C++20 协程
· 编码之道,道心破碎。
· 记一次 .NET 某发证机系统 崩溃分析
· 微服务架构学习与思考:SOA架构与微服务架构对比分析
· 历时半年,我将一个大型asp.net的零代码快速开发平台转成了java
· C#实现语音预处理:降噪、静音检测、自动增益(附Demo源码)
· 推荐五大AI+MCP自动化测试工具!
· 记一次 .NET 某无语的电商采集系统 CPU爆高分析
· Spring Boot 启动优化实践