Educational Codeforces Round 78 (Rated for Div. 2)

C - Berry Jam

题意:给2n个罐子,分别是[1,2n],站在[n,n+1]的中间,吃掉包含这个点的左边连续一段和右边连续一段,使得剩下的罐子红色的和蓝色的数量相等。吃最少的罐子。

题解:把红色蓝色变成+1和-1,那么就把左边的前缀和插进map里面,然后右边的后缀和在map里面查询相反数,查到就更新。注意因为是吃得越少越好所以同一个值,map里存的应该是最靠右的前缀。

注意!要加上为0的前缀和和后缀和!

不过现场可以看出来并造样例验证,也是能力提高了一点。

4
1 1 1 1 1 2 1 2

这个PP可真良心。

int n;
int a[2000005];
int prefix[2000005];
int suffix[2000005];
map<int, int> M;

void test_case() {
    scanf("%d", &n);
    M.clear();
    for(int i = 0; i <= 2 * n + 1; ++i) {
        prefix[i] = 0;
        suffix[i] = 0;
    }
    for(int i = 1; i <= 2 * n; ++i) {
        scanf("%d", &a[i]);
        if(a[i] == 2)
            a[i] = -1;
    }
    for(int i = 1; i <= 2 * n; ++i)
        prefix[i] = prefix[i - 1] + a[i];
    for(int i = 2 * n; i >= 1; --i)
        suffix[i] = suffix[i + 1] + a[i];
    int ans = 0;
    for(int i = 0; i <= n; ++i)
        M[prefix[i]] = i;
    for(int i = 2 * n + 1; i >= n + 1; --i) {
        int t = -suffix[i];
        if(M.count(t)) {
            ans = max(ans, M[t] + 2 * n + 1 - i);
            //cout << "i=" << M[t] << " j=" << 2 * n + 1 - i << endl;
        }
    }
    printf("%d\n", 2 * n - ans);
}

D - Segment Tree

题意:给2n个数字,每个数字[1,n]恰好出现2次,第一次称为l[i],第二次称为r[i]。任何两个部分交叉的线段代表的点之间连边,问连出来的是不是树。

题解:平衡树按r排序,遇到l就插进平衡树里面,那么每次就取出r<当前节点的r的点全部连一条边。当连的边不少于n条或者成环(实际上连的边有n条就一定会成环)就不可能是一棵树。当然,连的边不是n-1条也不会是一棵树。

好像对于这种有序性的还是平衡树方便又快,用堆还要反反复复取出来,常数小但是多个log。

struct DisjointSetUnion {
    static const int MAXN = 1000005;
    int n, fa[MAXN + 5], rnk[MAXN + 5];

    void Init(int _n) {
        n = _n;
        for(int i = 1; i <= n; i++) {
            fa[i] = i;
            rnk[i] = 1;
        }
    }

    int Find(int u) {
        int r = fa[u];
        while(fa[r] != r)
            r = fa[r];
        int t;
        while(fa[u] != r) {
            t = fa[u];
            fa[u] = r;
            u = t;
        }
        return r;
    }

    bool Merge(int u, int v) {
        u = Find(u), v = Find(v);
        if(u == v)
            return false;
        else {
            if(rnk[u] < rnk[v])
                swap(u, v);
            fa[v] = u;
            rnk[u] += rnk[v];
            return true;
        }
    }
} dsu;

int n;
int l[1000005], r[1000005];
int a[1000005];
set<pii> PQ;

void test_case() {
    scanf("%d", &n);
    PQ.clear();
    dsu.Init(2 * n);
    a[0] = a[2 * n + 1] = 0;
    for(int i = 1; i <= n; ++i) {
        scanf("%d%d", &l[i], &r[i]);
        a[l[i]] = i;
        a[r[i]] = -i;
    }
    int cntedge = 0;
    for(int i = 1; i <= 2 * n; ++i) {
        if(a[i] > 0) {
            int id = a[i];
            //cout << "id=" << id << endl;
            for(auto &e : PQ) {
                if(r[id] < e.first)
                    break;
                if(dsu.Merge(e.second, id)) {
                    //printf("%d - %d\n", e.second, id);
                    ++cntedge;
                    if(cntedge >= n) {
                        puts("NO");
                        return;
                    }
                } else {
                    //printf("%d - %d but \n", e.second, id);
                    puts("NO");
                    return;
                }
            }
            PQ.insert({r[id], id});
        } else {
            PQ.erase(PQ.begin());
            //int id = -a[i];
        }
    }
    if(cntedge == n - 1)
        puts("YES");
    else
        puts("NO");
}

E - Tests for problem D

题意:给一棵树,构造一个序列,使得D题可以复原这棵树。

题解:一开始看起来像广搜,但又不是广搜,又有点像深搜。在遍历一个点之后把它除父亲外所有的邻接点全部入栈然后把这个点的右边界弹出,就再也不会往后面连边了,而遍历这些邻接点的顺序就是先进先出,这样兄弟之间就是包含关系。注意!叶子节点是度数<=1的点!注意平凡的情况。

int root;
vector<int> G[500005];

void dfs1(int u, int p) {
    if(G[u].size() <= 1) {
        root = u;
        return;
    }
    for(auto &v : G[u]) {
        if(v == p)
            continue;
        dfs1(v, u);
        if(root)
            return;
    }
}

int ans[1000005], cnt;
int pa[500005];
stack<int> st;
void dfs(int u) {
    for(auto &v : G[u]) {
        if(v == pa[u])
            continue;
        ans[++cnt] = v;
        pa[v] = u;
        st.push(v);
    }
}

int l[500005], r[500005];

void test_case() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n - 1; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1, -1);
    ans[++cnt] = root;
    st.push(root);
    pa[root] = -1;
    while(st.size()) {
        int u = st.top();
        st.pop();
        dfs(u);
        ans[++cnt] = u;
    }
    for(int i = 1; i <= cnt; ++i) {
        int t = ans[i];
        if(l[t] == 0)
            l[t] = i;
        else
            r[t] = i;
        //printf("%d%c", ans[i], " \n"[i == cnt]);
    }
    for(int i = 1; i <= n; ++i)
        printf("%d %d\n", l[i], r[i]);
}

但是仔细一想,这个树上嵌套序列不是很像dfn序吗?只是父亲不再是嵌套子树了,而是和子树部分交叉,所以根据dfs来改是很自然的。下次不要怕。

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12074593.html

时间: 2024-11-05 22:58:01

Educational Codeforces Round 78 (Rated for Div. 2)的相关文章

Educational Codeforces Round 78 (Rated for Div. 2) D. Segment Tree

链接: https://codeforces.com/contest/1278/problem/D 题意: As the name of the task implies, you are asked to do some work with segments and trees. Recall that a tree is a connected undirected graph such that there is exactly one simple path between every

Educational Codeforces Round 78 (Rated for Div. 2) B. A and B

链接: https://codeforces.com/contest/1278/problem/B 题意: You are given two integers a and b. You can perform a sequence of operations: during the first operation you choose one of these numbers and increase it by 1; during the second operation you choos

Educational Codeforces Round 78 (Rated for Div. 2) A. Shuffle Hashing

链接: https://codeforces.com/contest/1278/problem/A 题意: Polycarp has built his own web service. Being a modern web service it includes login feature. And that always implies password security problems. Polycarp decided to store the hash of the password

【cf比赛记录】Educational Codeforces Round 78 (Rated for Div. 2)

比赛传送门 A. Shuffle Hashing 题意:加密字符串.可以把字符串的字母打乱后再从前面以及后面接上字符串.问加密后的字符串是否符合加密规则. 题解:字符串的长度很短,直接暴力搜索所有情况 // https://codeforces.com/contest/1278/problem/A #include<iostream> #include<cstdio> #include<cstring> using namespace std; int T; char

Educational Codeforces Round 78 (Rated for Div. 2) --补题

链接 直接用数组记录每个字母的个数即可 #include<bits/stdc++.h> using namespace std; int a[26] = {0}; int b[26] = {0}; int judge() { //cout<<"111"<<endl; for (int i = 0; i < 26; ++i) { if (a[i]!=b[i]) { return 0; } } return 1; } int main() { //

Educational Codeforces Round 78 (Rated for Div. 2) 题解

Shuffle Hashing A and B Berry Jam Segment Tree Tests for problem D Cards Shuffle Hashing \[ Time Limit: 2 s\quad Memory Limit: 256 MB \] 处理出 \(s_1\) 中各个字符出现的次数,然后双指针维护 \(s_2\) 中每一段长度为 \(len(s_1)\) 的串中字符出现的次数,如果存在某一段和 \(s_1\) 的字符次数相同,则是答案. view #inclu

Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam

Karlsson has recently discovered a huge stock of berry jam jars in the basement of the house. More specifically, there were 2n2n jars of strawberry and blueberry jam. All the 2n2n jars are arranged in a row. The stairs to the basement are exactly in

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars There are n pillars aligned in a row and numbered from 1 to n. Initially each pillar contains exactly one disk. The i-th pillar contains a disk having radius ai. You can move these disks

Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations

原文链接:https://www.cnblogs.com/xwl3109377858/p/11405773.html Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations You are given a sequence of n pairs of integers: (a1,b1),(a2,b2),…,(an,bn). This sequence is called bad if it is