zoukankan      html  css  js  c++  java
  • [Codeforces 1290C]Prefix Enlightenment

    Description

    题库链接

    给出长度为 (n) 的 01 串 (S),给定 (k) 个下标集合 (A_1,cdots,A_k),保证任意三个集合交集为空。每次操作选择一个集合,翻转 (S) 中对应位置。定义 (m_i) 为使前 (i) 个位置全为 (1) 所需的最少操作数(题目数据保证每个 (m_i) 都存在),求所有 (m_i) 的值。

    (1leq n,kleq 3 imes 10^5)

    Solution

    容易发现一个下标最多只会出现在两个集合中。

    假设只存在于一个集合中时,若该位为 (1),那么这个集合一定不会被选;如果这位置为 (0),那么这个集合被选。

    同样若这个位置存在于两个集合时,为 (1) 时,两个集合同选或同时不选;为 (0) 时,一个选择一个不选。

    基于上述原因,我们考虑维护一个带权并查集,每个集合拆成两个意思是选或者不选。

    (1)(n) 枚举位置,对每一位进行讨论。同时需要开一个虚点权值为 ( ext{inf}),将不会选到的状态(节点)连上去。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3e5+5, inf = 1e9;
    
    int n, kk, s, x, k[N][2];
    char ch[N];
    int fa[N<<1], val[N<<1];
    
    int find(int u) {return fa[u] ? fa[u] = find(fa[u]) : u; }
    void uni(int a, int b) {
        if (find(a) == find(b)) return;
        val[find(b)] += val[find(a)];
        fa[find(a)] = find(b);
    }
    int mix(int a) {return min(val[find(a)], val[find(a+kk)]); };
    int main() {
        scanf("%d%d%s", &n, &kk, ch+1);
        for (int i = 1; i <= kk; i++) {
            scanf("%d", &s);
            while (s--) {
                scanf("%d", &x);
                k[x][bool(k[x][0])] = i;
            }
        }
        for (int i = 1; i <= kk; i++) val[i] = 1;
        val[kk+kk+1] = inf;
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            if (k[i][0] == 0) goto qwq;
            if (ch[i] == '1') {
                if (k[i][1]) {
                    if (find(k[i][0]) == find(k[i][1])) goto qwq;
                    ans -= mix(k[i][0])+mix(k[i][1]);
                    uni(k[i][0], k[i][1]), uni(k[i][0]+kk, k[i][1]+kk);
                    ans += mix(k[i][0]);
                } else {
                    ans -= mix(k[i][0]);
                    uni(k[i][0], kk+kk+1);
                    ans += mix(k[i][0]);
                }
            } else {
                if (k[i][1]) {
                    if (find(k[i][0]) == find(k[i][1]+kk)) goto qwq;
                    ans -= mix(k[i][0])+mix(k[i][1]);
                    uni(k[i][0], k[i][1]+kk), uni(k[i][0]+kk, k[i][1]);
                    ans += mix(k[i][0]);
                } else {
                    ans -= mix(k[i][0]);
                    uni(k[i][0]+kk, kk+kk+1);
                    ans += mix(k[i][0]);
                }
            }
            qwq :
                printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    远程获取图片尺寸
    python httplib get和post获取数据
    python 之 logging
    php artisan常用方法
    html页面制作css基本设置
    zlib-1.2.7/libpng-1.5.9 instead of zlib-1.2.8/libpng-1.6.6
    shell脚本自动拉起启动程序
    php截取中文无乱码
    路飞学城1之课程与课程详细
    vuex(数据商店实现思想)day06
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/12309785.html
Copyright © 2011-2022 走看看