分治WA了,不知道怎么回事
查看原帖
分治WA了,不知道怎么回事
931963
HuangDY_FZU楼主2024/12/18 11:18

使用分治法

#include <stdio.h>
#include <inttypes.h>
#include <algorithm>
#include <functional>
using namespace std;
enum
{
	MAXN = 200001,
};

int n;
int64_t a[MAXN], b[MAXN], s, cnt, sum[MAXN], mn[MAXN];

void calc_sum_mn(int le, int ri)
{
	int mid = (le + ri) / 2, i = mid;
	sum[i] = b[i];
	mn[i] = a[i];
	while (--i >= le)
	{
		sum[i] = b[i] + sum[i + 1];
		mn[i] = min(a[i], mn[i + 1]);
	}

	i = mid + 1;
	sum[i] = b[i];
	mn[i] = a[i];
	while (++i <= ri)
	{
		sum[i] = b[i] + sum[i - 1];
		mn[i] = min(a[i], mn[i - 1]);
	}
}

void work(int le, int ri)
{
	if (le == ri)
	{
		cnt += (a[le] + b[le] <= s);
		return;
	}
	int mid = (le + ri) / 2;
	work(le, mid);
	work(mid + 1, ri);
	calc_sum_mn(le, ri);

	/* 最小值在左半边 */
	for (int i = mid, p = mid; i >= le; i--)
	{
		while (++p <= ri && mn[p] >= mn[i]) {}
		if (--p == mid) continue;
		int64_t* q = upper_bound(sum + mid + 1, sum + p + 1, s - sum[i] - mn[i]);
		cnt += int64_t(q - (sum + mid + 1));
	}

	/* 最小值在右半边 */
	for (int j = mid + 1, p = mid + 1; j <= ri; j++)
	{
		while (--p >= le && mn[p] >= mn[j]) {}
		if (++p == mid + 1) continue;
		int64_t* q = lower_bound(sum + p, sum + mid + 1, s - sum[j] - mn[j], greater<int64_t>());
		cnt += int64_t(sum + mid + 1 - q);
	}
}

int main(void)
{
	(void)scanf("%d%" SCNd64, &n, &s);
	for (int i = 0; i < n; i++) (void)scanf("%" SCNd64, &a[i]);
	for (int i = 0; i < n; i++) (void)scanf("%" SCNd64, &b[i]);
	work(0, n - 1);
	printf("%" PRId64, cnt);
	return 0;
}
2024/12/18 11:18
加载中...