[CF1687C] Sanae and Giant Robot 题解

[CF1687C] Sanae and Giant Robot

并查集?不,这是一道奇妙的转化题。

首先,设 ci=aibi,则原题操作转化为:当某个 [li,ri] 满足 j=liricj=0 时,可以将 cliri 清零。目标是让 ci 全部清零。

第二步,观察到第一步中的 j=liricj 是连续子段和的形式,考虑构造前缀和。设 si=j=1icj。则原题操作转化为:当某个 sli1=sri 时,可以将 sliri 全部赋值为 sri,目标仍是让 si 全部清零。

第三步,注意到因为目标是清零 si,所以如果 sli1=sri0,操作是不优的,我们只应在 sli1=sri=0 时操作。

现在原题变得很简单了。我们处理出 si 后,每次找一对 sli1=sri=0,然后清零 sliri,直到不能再操作为止。最终若 si 全部清空,则为 YES;反之则为 NO

具体维护方面,用一个 set 维护所有 si0i,用一个 queue 维护所有 si=0i,用一个 vector 记录下来所有 l1,r 的相对关系。从 queue 中取出一个 si=0 的点 i,遍历所有和 i 相连的点 j,若 sj=0 则清空 set 中 [i,j] 的元素,最后检查 set 是否为空即可。

#include<bits/stdc++.h>
using namespace std;

using ll=long long;
constexpr int MAXN=2e5+5;
int T,n,m,a[MAXN],b[MAXN];
ll s[MAXN];
vector<int>g[MAXN];
set<int>st;
queue<int>q;

int main(){
	cin.tie(nullptr)->sync_with_stdio(0);
	cin>>T;
	while(T--){
		cin>>n>>m;
		st.clear();
		q.emplace(0);
		for(int i=0;i<=n;++i) g[i].clear();
		for(int i=1;i<=n;++i) cin>>a[i];
		for(int i=1;i<=n;++i){
			cin>>b[i];
			s[i]=s[i-1]+a[i]-b[i];
			if(s[i]) st.emplace(i);
			else q.emplace(i);
		}
		for(int i=1,u,v;i<=m;++i){
			cin>>u>>v;
			g[u-1].emplace_back(v);
			g[v].emplace_back(u-1);
		}
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(auto v:g[u]){
				if(s[v]) continue;
				int l=min(u,v),r=max(u,v);
				for(auto it=st.lower_bound(l);it!=st.end()&&*it<=r;it=st.erase(it))
					s[*it]=0,q.emplace(*it);
			}
		}
		cout<<(st.empty()?"YES\n":"NO\n");
	}
	return 0;
}
posted @   Laoshan_PLUS  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示