Codeforces Round #612

  • Garland

    • 题意
    • 题解
    • 代码
  • Numbers on Tree
    • 题意
    • 题解
    • 代码

Garland

题目链接 http://codeforces.com/contest/1286/problem/A

题意

给出一串灯泡,灯泡上编号为 1~n 的一个排列,其中一些灯泡掉落。
定义整串的权值为相邻灯泡编号奇偶不同的对数,求放回灯泡后的最小权值。

题解

编号只有奇偶性有用。统计掉落灯泡编号的奇数个数和偶数个数。缺少灯泡的间隙分为四种,奇数间隙(两端为奇数),偶数间隙(两端为偶数),奇偶间隙(两端数字奇偶性不同),两端的间隙。
对于奇数间隙和偶数间隙,分别填充奇数灯泡和偶数灯泡,剩余灯泡不够无法填充,则权值 +2(因为一定填充了奇偶性不同的一段(个)灯泡);奇偶间隙直接权值 +1;两端的间隙由于在两端,填充奇偶性不同的灯泡也只会让权值加 1。

代码

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define Nmax 120
int ls[Nmax];
int N;
int cnt[2];
vector<pair<int, int> > sm[2];
int main()
{
    scanf("%d", &N);
    cnt[0] = N/2;
    cnt[1] = N - cnt[0];
    for (int i = 1; i <= N; i++)
    {
        scanf("%d", &ls[i]);
        if (ls[i] == 0)
        {
            ls[i] = -1;
        }
        else
        {
            ls[i] %= 2;
            cnt[ls[i]]--;
        }
    }
    if (cnt[0] + cnt[1] == N)
    {
        if (cnt[0] && cnt[1])
        {
            printf("1\n");
        }
        else
        {
            printf("0\n");
        }
        return 0;
    }
    for (int i = 1; i <= N; i++)
    {
        if (ls[i] != -1)
        {
            ls[0] = ls[i];
            break;
        }
    }
    for (int i = N; i >= 1; i--)
    {
        if (ls[i] != -1)
        {
            ls[N+1] = ls[i];
            break;
        }
    }
    int k;
    int ans = 0;
    int lst = ls[0];
    int ct = 0;
    for (int i = 1; i <= N+1; i++)
    {
        if (i == 1 || i == N+1)
        {
            k = 1;
        }
        if (ls[i] == -1)
        {
            ct++;
        }
        else
        {
            if (lst == ls[i]) {
                sm[lst].push_back(make_pair(k, ct));
                k = 0;
                ct = 0;
            }
            else {
                ans++;
                k = 0;
                ct = 0;
                lst = ls[i];
            }
        }
    }
    sort(sm[0].begin(), sm[0].end());
    sort(sm[1].begin(), sm[1].end());
    for (int j = 0; j < 2; j++) {
        for (int i = 0; i < sm[j].size(); i++) {
            if (sm[j][i].second <= cnt[j]) {
                cnt[j] -= sm[j][i].second;
            }
            else {
                if (sm[j][i].first == 0) {
                    ans += 2;
                }
                else {
                    ans += 1;
                }
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

Numbers on Tree

题目链接 http://codeforces.com/contest/1286/problem/B

题意

给定一棵 n 个结点的树,每个节点有一个未知权值 \(a_i\)。已知每棵子树中权值小于子树根节点权值的结点个数 \(c_i\),求一个可行性的权值方案。

题解

显然子树根结点权值是子树中第 \(c_i+1\) 小的,兄弟子树间权值互不影响。只需要处理完当前结点的子节点后,将当前结点插在第 \(c_i+1\) 小的位置即可。\(n \leq 2000\),\(n^2\) 复杂度可以接受,任意插入方式都可。

代码

#include <cstdio>
#include <list>
#include <vector>
using namespace std;
#define Nmax 2020
list<int> ls;
int N;
vector<int> tr[Nmax];
int C[Nmax];
int A[Nmax];
bool flag = false;
void DFS(int x, list<int>::iterator oit) {
    list<int>::iterator it;
    it = oit;
    for (int i = 0; i < tr[x].size(); i++)
    {
        DFS(tr[x][i], it);
        if (flag)
            return;
        it = ls.end();
        it--;
    }
    oit++;
    for (int i = 0; i < C[x]; i++) {
        if (oit == ls.end()) {
            flag = true;
            return;
        }
        else {
            oit++;
        }
    }
    ls.insert(oit, x);
}
int main() {
    ls.push_back(0);
    list<int>::iterator it;
    it = ls.begin();
    scanf("%d", &N);
    int p, c;
    for (int i = 1; i <= N; i++)
    {
        scanf("%d %d", &p, &C[i]);
        tr[p].push_back(i);
    }
    DFS(tr[0][0], it);
    if (flag) {
        printf("NO\n");
    }
    else {
        printf("YES\n");
        int i = 1;
        for (it++; it != ls.end(); it++) {
            A[*it] = i++;
        }
        for (int i = 1; i <= N; i++) {
            printf("%d ", A[i]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KZNS/p/codeforces-round-612.html

时间: 2024-10-08 20:44:13

Codeforces Round #612的相关文章

Codeforces Round #612 (Div. 2)

A A后面连续的P最长有几个 O(n) #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #define ll long long using namespace std; const int maxn = 1e5+5; const int inf = 0x3f3f3f3f; int main(){ int t;

Codeforces Round #612题解

A题 只需要找到A中后面跟的最长的p串是几个即可 #include<iostream> #include<cstring> #include<string> #include<map> #include<vector> #include<cstdio> using namespace std; int main(){ int t; cin>>t; string s; int n; int i; while(t--){ ci

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

直 接看所有A后面连续P的个数最大值 #include<cstring> #include<cstdio> #include<set> #include<iostream> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, s, t) for (int i = s; i < (int)t; i++) #define fi first #define se sec

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

Codeforces Round #400 C 前缀和,思维

ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) C. Molly's Chemicals 题意:n个数,问有多少个区间的和是k的次方数,即sum([l, r])=k^x, x>=0. abs(k)<=10. tags:一开始O(n^2)统计,果然炸了.. 这题要在统计到第 i 个数时,看s[i]-k^x是否在前面出现过.因为k指数增长很快,这样就是O(n). // #400 #include<b

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd