CF1687C

ci=aibi

那么原题操作变成若区间 [l,r]c 和为 0,那么可以将这段区间的 c 都变成 0

最终目标是 c 全部变成 0

sumi 表示 c 的前缀和。

此时操作变成,若 suml1=sumr,可以将这段区间的 sum 都变成 suml1

最终目标是 sum 全部变成 0

不难发现若 suml1=sumr0,执行这个操作是不优的,于是应该只在 suml1=sumr=0 的时候执行操作。

于是接下来就是每次找一对 suml1=sumr=0,然后将这段区间的 sum 全部置 0,直到不能操作为止。

最终如果 sum 全变成 0 了就输出 YES,否则是 NO

但是暴力 BFS 扩展时间复杂度是 O(nm) 的,考虑优化这个过程。

可以用 set 维护当前非 0 的位置,每次将当前更新的区间中的非 0 位置全部取出来放进队列里继续 BFS,然后在 set 中删去这些点。

不难发现这样复杂度是 O((n+m)logn) 的。

Code:

#include <bits/stdc++.h>
using namespace std;
#define YES return printf("YES\n"), void()
#define NO return printf("NO\n"), void()
#define lb lower_bound
typedef long long ll;
const int N = 200005;
int T;
int n, m;
int a[N], b[N], diff[N]; ll sum[N];
vector <int> g[N];
set <int> S;
queue <int> q;

void upd(int l, int r) {
	if (l > r) swap(l, r);
	for (auto it = S.lb(l); it != S.end() && (*it) <= r; it = S.lb(l)) q.push(*it), S.erase(it);
}

void solve() {
	scanf("%d%d", &n, &m);
	S.clear();
	for (int i = 0; i <= n; ++i) g[i].clear();
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), diff[i] = b[i] - a[i], sum[i] = sum[i - 1] + diff[i];
	for (int i = 1, l, r; i <= m; ++i) scanf("%d%d", &l, &r), g[l - 1].push_back(r), g[r].push_back(l - 1);
	if (sum[n]) NO;
	for (int i = 0; i <= n; ++i) if (sum[i]) S.insert(i); else q.push(i);
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int v : g[u]) if (!S.count(v)) upd(u, v);
	}
	if (!S.empty()) NO;
	YES;
}

int main() {
	scanf("%d", &T);
	while (T--) solve();
	return 0;
}
posted @   Kobe303  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示