zoukankan      html  css  js  c++  java
  • 题解 CF1227G 【Not Same】

    (Large exttt{CF1227G Not Same })

    标签:构造

    疑似水2600?

    题意

    给定大小为 (n) 的序列 (a) , 满足 (1 le a_i le n)

    你需要执行至多 (n+1) 次操作使得所有数变为 (0),每次操作你可以把一个子集的元素都 (-1),要求每次操作的子集互不相同。

    (n le 1000)

    思路

    好像和题解区的构造方法都不太相同,但是很好理解。

    首先假设最后序列有 (n + 1) 个。

    因为最后的操作序列没有两两相同,我们从序列的角度来看,一开始是都相同的,我们认为它们都是在同一个集合中。

    (以下“序列”即为集合中的元素)

    操作即为每次由第 (i) 个数字 (a_i),给 (a_i) 个序列的末尾加上 (1),并给剩下 (n + 1 - a_i) 个序列末尾加上 (0),注意到这一步可以使一些相同的序列变得不同,即使同一个集合中的元素通过在末尾添加了不同的 bit 变成了不相同,这时候就可以把加不同 bit 的这些元素拉出来变成一个新的集合(比如加 (0) 的不动,放 (1) 的新拉出来一个集合)。

    然后我们注意到 (1 le a_i le n) 这说明每个 (a_i) 对序列的操作至少有一个 (0),至少有一个 (1)

    也就是说每个数如果操作分配的好,一定至少有一个集合大小 (ge 2) 的集合可以被分成两份,又因为初始集合大小为 (n + 1)(n) 次一定分得 (n + 1) 个不同的集合。

    代码

    int a, s[N + 5], ans[N + 5][N + 5], top = 1;
    vector<int> q[N + 5];
    
    void add(int n, int j) {
        rep(i, 0, siz(q[n]) - 1) ans[q[n][i]][j] = 1;
    }
    
    void divide(int n, int p0, int p1, int j) {
        ++top;
        rep(i, 1, p0) q[top].PB(q[n][siz(q[n]) - 1]), q[n].pop_back();
        add(n, j);
    }
    
    signed main() {
        // freopen("in1.in", "r", stdin);
        // freopen("out.out", "w", stdout);
        a = read();
        rep(i, 1, a) s[i] = read(), q[1].PB(i);
        q[1].PB(a + 1);
        rep(i, 1, a) {
            int p0 = a + 1 - s[i], p1 = s[i];
            int _top = top;
            rep(j, 1, _top) {
                if (siz(q[j]) == 1) {
                    if (p1 > p0) add(j, i), --p1;
                    else --p0;
                }
                else if (!p0) {
                    p1 -= siz(q[j]);
                    add(j, i);
                }
                else if (!p1) p0 -= siz(q[j]);
                else {
                    int q0 = min(p0, siz(q[j]) - 1), q1 = siz(q[j]) - q0;
                    divide(j, q0, q1, i);
                    p0 -= q0;
                    p1 -= q1;
                }
            }
        }
        printf("%d
    ", a + 1);
        for (int i = 1; i <= a + 1; ++i, puts("")) rep(j, 1, a) printf("%d", ans[i][j]);
        return 0;
    }
    
  • 相关阅读:
    Android客户端与PCServer端socket通信加密方法
    Android的进程优先级与进程回收
    Android学习下载网络图片
    Java Socket通信实现文件传输/图片传输
    python 知识整理
    vmware 安装 centos8 步骤
    mysql 开启事务的 sql 写法
    团队项目七天冲刺 第二天
    测试的计划和执行
    Contentdisposition
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/15007913.html
Copyright © 2011-2022 走看看