CF1687C
令 ci=ai−bi。
那么原题操作变成若区间 [l,r] 的 c 和为 0,那么可以将这段区间的 c 都变成 0。
最终目标是 c 全部变成 0。
令 sumi 表示 c 的前缀和。
此时操作变成,若 suml−1=sumr,可以将这段区间的 sum 都变成 suml−1。
最终目标是 sum 全部变成 0。
不难发现若 suml−1=sumr≠0,执行这个操作是不优的,于是应该只在 suml−1=sumr=0 的时候执行操作。
于是接下来就是每次找一对 suml−1=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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!