• AtCoder Regular Contest 80


    链接

    C. 4-adjacent

    给定序列$a_i$,询问是否存在一个排列,满足$a_{p[i]}* a_{p[i + 1]}$是4的倍数

    贪心构造

    首先把只是2的倍数的数拿出来,放在最右边

    前面把是1的倍数的数和是4的倍数的数交替放置即可

    之后随意判断即可

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define ri register int
    int n, n2, n4, flag;
    
    int main() {
        n = read();
        for(ri i = 1; i <= n; i ++) {
            int x = read();
            if(x % 4 == 0) n4 ++;
            else if(x % 2 == 0) n2 ++;
        }
        n -= n2;
        if(n & 1) {
            if(n2) flag = (n4 > n / 2);
            else flag = (n4 >= n / 2);
        }
        else flag = (n4 >= n / 2);
        if(flag) printf("Yes
    ");
        else printf("No
    ");
        return 0;
    }

    D.Grid Coloring

    对$R*W$的格子进行染色,需要使颜色$i$的出现次数为$c_i$

    且同一颜色形成联通块,询问是否可行并给出一组方案

    S形涂色即可

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define ri register int
    #define sid 105
    
    int H, W, n, id;
    int col[sid][sid], ord[sid * sid];
    
    int main() {
        scanf("%d%d%d", &H, &W, &n);
        for(ri i = 1; i <= n; i ++) {
            int x; scanf("%d", &x);
            while(x --) ord[++ id] = i;
        }
        id = 0;
        for(ri i = 1; i <= H; i ++)
        for(ri j = 1; j <= W; j ++)
        col[i][j] = ord[++ id];
        for(ri i = 2; i <= H; i += 2)
        reverse(col[i] + 1, col[i] + W + 1);
        for(ri i = 1; i <= H; i ++, printf("
    "))
        for(ri j = 1; j <= W; j ++)
        printf("%d ", col[i][j]);
        return 0;
    }

    E.Young Maids

    题意略复杂,直接看原题面吧...

    从前往后去贪心

    每次选择的一定是某个区间中的奇(偶)最小值后其后的偶(奇)最小值

    注意奇偶的判断即可

    复杂度$O(n log n)$

    一开始表示平衡树裸题,然后点开题解,还是打st表吧

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define sid 200050
    #define inf 1e9
    #define ri register int
    
    int n;
    int bit[sid], l_g[sid];
    int st[sid][21][2], v[sid][2], arc[sid];
    
    void Init() {
        for(ri i = 0; i <= 30; i ++) bit[i] = 1 << i;
        for(ri i = 2; i <= n; i ++) l_g[i] = l_g[i >> 1] + 1;
        for(ri o = 0; o <= 1; o ++)
        for(ri i = 1; i <= n; i ++) st[i][0][o] = v[i][o];
        for(ri o = 0; o <= 1; o ++)
        for(ri j = 1; bit[j] <= n; j ++)
        for(ri i = 1; i + bit[j] - 1 <= n; i ++)
        st[i][j][o] = min(st[i][j - 1][o], st[i + bit[j - 1]][j - 1][o]);
    }
    
    inline int rmq(int l, int r, int o) {
        int lg = l_g[r - l + 1];
        return min(st[l][lg][o], st[r - bit[lg] + 1][lg][o]);
    }
    
    struct Seg {
        int v, l, r;
        friend bool operator < (Seg a, Seg b)
        { return a.v > b.v; }
    };
    priority_queue <Seg> q;
    
    int main() {
        n = read();
        for(ri i = 1; i <= n; i ++) {
            int w = (v[i][(i ^ 1) & 1] = read());
            v[i][i & 1] = inf; arc[w] = i;
        }
        Init();
        q.push({ rmq(1, n, 0), 1, n });
        while(!q.empty()) {
            Seg tmp = q.top(); q.pop();
            int w1 = tmp.v, pw1 = arc[w1];
            int w2 = rmq(pw1 + 1, tmp.r, pw1 & 1), pw2 = arc[w2];
            printf("%d %d ", w1, w2);
            if(tmp.l != pw1) q.push({ rmq(tmp.l, pw1 - 1, (tmp.l + 1) & 1), tmp.l, pw1 - 1 });
            if(pw1 + 1 != pw2) q.push({ rmq(pw1 + 1, pw2 - 1, pw1 & 1), pw1 + 1, pw2 - 1 });
            if(pw2 != tmp.r) q.push({ rmq(pw2 + 1, tmp.r, pw2 & 1), pw2 + 1, tmp.r });
        }
        return 0;
    }

    F.Prime Flip

    有$n$个位置的牌向上,

    每次可以选定一段长为$p$($p$为奇质数)的区间,翻转这个区间

    询问最少几次能使所有牌向下

    考虑构造新序列$e_i = [a_i = a_{i + 1}]$,$a_i$表示向上还是向下

    当$e_i$全部为0时,原序列全部向下

    那么,原题的区间操作转化为同时对两个点翻转

    两个点匹配有3种情况

    1.相差为奇质数,需要1次

    2.相差为偶数,需要2次

    3.否则,需要3次

    对于第一种情况,做二分图匹配

    第二种情况,讨论

    第三种情况,讨论

    对我而言是神题,不会做.....

    然而有一堆AK的神仙....

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define ri register int
    #define ssd 10000010
    #define sid 205
    
    int n, N = 1e7;
    int pr[ssd / 10], tot;
    int nj, no, js[sid], os[sid];
    bool nop[ssd], e[ssd];
    
    int tim, vis[sid], mat[sid];
    bool ex[sid][sid];
    
    inline void Init() {
        nop[1] = 1;
        for(ri i = 2; i <= N + 1; i ++) {
            if(!nop[i]) pr[++ tot] = i;
            for(ri j = 1; j <= tot; j ++) {
                int nx = i * pr[j]; if(nx > N + 1) break;
                nop[nx] = 1; if(i % pr[j] == 0) break;
            }
        }
        nop[2] = 1;
    }
    
    inline int dfs(int o) {
        for(int i = 1; i <= no; i ++)
        if(ex[o][i] && vis[i] != tim) {
            vis[i] = tim;
            if(!mat[i] || dfs(mat[i])) 
            return mat[i] = o, 1;
        }
        return 0;
    }
    
    int main() {
        Init();
        cin >> n;
        for(ri i = 1; i <= n; i ++) { int x; cin >> x; e[x] = 1; }
        
        for(ri i = 1; i <= N + 1; i ++)
        if(e[i] != e[i - 1]) {
            if(i & 1) js[++ nj] = i;
            else os[++ no] = i;
        }
    
        for(ri i = 1; i <= nj; i ++)
        for(ri j = 1; j <= no; j ++)
        if(!nop[abs(js[i] - os[j])]) ex[i][j] = 1;
    
        int num = 0, ans = 0;
    
        for(ri i = 1; i <= nj; i ++)
        ++ tim, num += dfs(i);
    
        nj -= num; no -= num;
        ans = num + nj / 2 * 2 + no / 2 * 2 + (nj & 1) * 3;
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    Java 代码中如何调用 第三方Api
    如何编写README.md
    Gof 设计模式
    系统架构师-笔记
    我的账户
    软件设计师-成绩查询
    spring data jpa
    日志 logback
    spring boot 整合 Camunda
    Spring 中 bean 的生命周期?
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9709737.html
Copyright © 2020-2023  润新知