Codeforces Round #612 (Div. 2)

Posted kisekipurin2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #612 (Div. 2)相关的知识,希望对你有一定的参考价值。

https://codeforces.com/contest/1287/

A - Angry Students

D - Numbers on Tree

题意:给一棵有根树,规定每个数的子树中有多少个节点的val比根节点的严格小。给这棵树填上任意一种合法的val(每个值都在[1,10^9]且满足上一句话)或报告不存在。

题解:树的这类问题可能都是先往递归的方向考虑,假如是叶子,不用多说之间返回1,否则是中间节点。假如中间节点只有一棵子树,而且子树中的值是相异的,那么随便插进去然后把后面的数往后面挤,得到的也还是值全部相异的树。否则至少有两棵子树,假如他们的值也都是相异的也可以仿照上面解决,可惜搞不得,有可能不存在一个位置刚好满足要求。

  1. 这时候很显然的子树之间是没有关系的,可以给一棵子树的值整体提高一个水平,使得得到的值也是相异的,最简单的是加上上一棵子树的最大值(而不一定是size,假如没有进行算不并列的排名的话)。

  2. 事实上并不一定需要同一棵子树占据同一段连续的位置,直接全部混在一起算不并列的排名也可以。

int n, root;

int c[2005];

vector<int> G[2005];
vector<pii> vec[2005];

void dfs(int u) {
    for(auto &v : G[u]) {
        dfs(v);
        for(auto &j : vec[v])
            vec[u].push_back(j);
    }
    if(c[u] > vec[u].size()) {
        puts("NO");
        exit(0);
    }
    sort(vec[u].begin(), vec[u].end());
    for(int i = 0; i < vec[u].size(); ++i)
        vec[u][i].first = i + 1;
    vec[u].insert(vec[u].begin() + c[u], {c[u] + 1, u});
    for(int i = c[u] + 1; i < vec[u].size(); ++i)
        ++vec[u][i].first;
}

void test_case() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        int p;
        scanf("%d%d", &p, &c[i]);
        if(p)
            G[p].push_back(i);
        else
            root = i;
    }
    dfs(root);
    for(auto &j : vec[root])
        swap(j.first, j.second);
    sort(vec[root].begin(), vec[root].end());
    puts("YES");
    for(auto &j : vec[root])
        printf("%d ", j.second);
    puts("");
}

注意vector中insert是一个迭代器,而且确实可以在 for auto 中进行交换(应该在遍历中不会改变其他元素的操作都可以吧?)

以上是关于Codeforces Round #612 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #612题解

Codeforces Round #612 (Div. 2)

codeforces round #612解题报告A~D

Codeforces Round #612 (Div. 2)

Codeforces Round #612 (Div. 2) (A-D)

Codeforces Round #436 E. Fire(背包dp+输出路径)