• #796 Div.2 F. Sanae and Giant Robot set *


    1688F
    set,2500

    题意

    给出 a , b a,b a,b 两个序列,并给出 m m m 个区间 [ l i , r i ] [l_i,r_i] [li,ri],每次可以从它们中满足 ∑ i = l r a i = ∑ i = l r b i \sum_{i=l}^ra_i=\sum_{i=l}^rb_i i=lrai=i=lrbi 的区间中任选一个,对这个区间的所有数执行 a i = b i a_i=b_i ai=bi,问能否经过若干次操作,使得 a a a 序列和 b b b 序列相同?

    思路

    区间可以被选当且仅当这个区间内两序列和相同,也就是差为0,所以用数组 s i s_i si 表示两个数组前缀和之差,即 s i = s i − 1 + a i − b i s_i=s_{i-1} + a_i - b_i si=si1+aibi,则区间 [ l , r ] [l,r] [l,r] 可以被选当且仅当 s l − 1 = s r s_{l-1}=s_r sl1=sr,且操作过后 s l − 1 = s l = . . . = s r s_{l-1}=s_l=...=s_r sl1=sl=...=sr,最终目标是令 s s s 数组全为 0 0 0 ,因此选 s l − 1 ≠ 0 s_{l-1}\neq 0 sl1=0 的没有意义。

    所以题可以转化为:对于区间 [ l , r ] [l,r] [l,r] ,如果 s l − 1 = s r = 0 s_{l-1}=s_{r}=0 sl1=sr=0 ,则使 s l − 1 = s l = . . . = s r = 0 s_{l-1}=s_l=...=s_r=0 sl1=sl=...=sr=0 , 是否可以使 s s s 全为 0 0 0

    可以用 queue 存数组 s s s 已经为0的位置,set 存还不是0的位置,依次遍历已经为0的位置所连的边,若另一点也为0,则遍历范围在这个区间内的 set 中元素并加入队列。如果最终队空但 set 未空,则无解。每个点至多加入队列一次,时间复杂度 O ( ( n + m ) log ⁡ n ) O((n+m)\log n) O((n+m)logn)

    代码

    int n, m;
    int a[maxn], b[maxn], s[maxn];
    vector<int> e[maxn];
    void solve() {
        cin >> n >> m;
        set<int> se;
        for(int i = 1; i <= n; i++) {
        	cin >> a[i];
        	se.insert(i);
        }
        for(int i = 1; i <= n; i++) {
        	cin >> b[i];
        	s[i] = s[i-1] + a[i] - b[i];
        	e[i].clear();
        }
        e[0].clear();
        //se 表示非0的位置
        for(int i = 1; i <= m; i++) {
        	int x, y;
        	cin >> x >> y;
        	x--;
        	e[x].pb(y);
        	e[y].pb(x);
        }
        queue<int> q;
        for(int i = 0; i <= n; i++) {
        	if(!s[i]) {
        		q.push(i);
        		se.erase(i);
        	}
        }
        while(!q.empty()) {
        	int x = q.front();
        	q.pop();
        	for(int i = 0; i < e[x].size(); i++) {
        		int y = e[x][i];
        		if(s[y]) continue;
        		int l = min(x, y), r = max(x, y);
        		auto itl = se.lower_bound(l), itr = se.upper_bound(r);
        		for(auto it = itl; it != itr; it++) {
        			s[*it] = 0;
        			q.push(*it);
        		}
        		se.erase(itl, itr);
        	}
        }
        if(!se.empty()) {
        	cout << "NO\n";
        }
        else {
        	cout << "YES\n";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
  • 相关阅读:
    【微服务】Nacos Discovery--服务治理
    【cmake】彻底弄懂cmake中的可见性/传递性 INTEFACE 问题
    Nginx 笔记(五)nginx+keepalived高可用集群(主从+双主)
    中秋节快乐--祝诸佬们今后月来月靓
    C++ Primer Plus第五版笔记(p101-150)
    百分点科技连续四年登榜“中关村高成长企业TOP100”
    Python基础入门---conda 如何管理依赖包以及复制相同环境的
    【校招VIP】前端计算机网络之webSocket相关
    puppeteer的简单使用
    万字摸透Redis、MySQL和ZooKeeper分布式锁,还不会的出来!
  • 原文地址:https://blog.csdn.net/m0_59273843/article/details/125487127