[USACO 20JAN] Farmer John Solves 3SUM G(巧妙的前缀和思想) | 错题本

文章目录

题目

[USACO 20JAN] Farmer John Solves 3SUM G

分析

考虑初始化出所有答案,由于一个面(二维)内答案可能很多,这种情况下可以考虑算二维的单点,然后二维前缀和即可。本题可以计算 i ∈ ( l , r ) i \in (l, r) i(l,r) 满足 a i + a l + a r = 0 a_i + a_l + a_r = 0 ai+al+ar=0 i i i 数量存入 Sum[l][r],然后对 Sum 求一遍二维前缀和,可以得到 j ∈ [ 1 , l ] , k ∈ [ 1 , r ] , i ∈ ( j , k ) , j ≠ k j \in [1, l], k \in [1, r], i \in (j, k), j \neq k j[1,l],k[1,r],i(j,k),j=k 满足 a i + a j + a k = 0 a_i + a_j + a_k = 0 ai+aj+ak=0 的数量,询问时直接前缀和容斥一下输出即可。

代码

#include <bits/stdc++.h>

int Read() {
	int x = 0; bool f = false; char c = getchar();
	while (c < '0' || c > '9')
		f |= c == '-', c = getchar();
	while (c >= '0' && c <= '9')
		x = x * 10 + (c ^ 48), c = getchar();
	return f ? -x : x;
}

const int MAXN = 5000;
const int MAXA = 1000000;

int N, Q;
int A[MAXN + 5];
int Cnt[MAXA * 2 + 5];
long long Sum[MAXN + 5][MAXN + 5];

int main() {
	N = Read(), Q = Read();
	for (int i = 1; i <= N; i++)
		A[i] = Read() + MAXA;
	for (int i = 1; i <= N; i++) {
		for (int j = i + 1; j <= N; j++) {
			int fnd = 3 * MAXA - A[i] - A[j];
			if (j > i + 1 && fnd >= 0 && fnd <= 2 * MAXA)
				Sum[i][j] = Cnt[fnd];
			Cnt[A[j]]++;
		}
		for (int j = i + 1; j <= N; j++)
			Cnt[A[j]]--;
	}
	for (int i = 1; i <= N; i++)
		for (int j = 1; j <= N; j++)
			Sum[i][j] += Sum[i][j - 1] + Sum[i - 1][j] - Sum[i - 1][j - 1];
	while (Q--) {
		int lft = Read(), rgt = Read();
		printf("%lld\n", Sum[rgt][rgt]- Sum[lft - 1][rgt] - Sum[rgt][lft - 1] + Sum[lft - 1][lft - 1]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值