Codeforces Round #386 (Div. 2)(A-E)(水题 + deque模拟 + 思维 + 构造&贪心 + set模拟)

时间:2023-01-13 15:51:11

A

题意:制作物品的三种材料用比为1:2:4,给出三种物品的用量,问最多能制作出多少质量的物品。

思路:判断每种材料最多可以制作出多少个成品,取最小值即可。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;

int main()
{
    int a, b, c;
    cin>>a>>b>>c;
    a/=1;
    b/=2;
    c/=4;

    int ans = min(a, min(b, c));

    cout<<ans*7<<endl;
}

B

题意:给出一种对字符串的编码方式,先取字符串的中值,然后一左一右顺序取值,形成新的字符串,给出新串求原串

思路:可以从新串逆推转移公式,然后我比较懒就用deque逆模拟特判串长奇偶性就好了

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;

deque<char > q;

int main()
{

    q.clear();

    int n;
    string s;
    cin>>n>>s;
    for(int i=0; i<n; i++)
    {
        if(i==0 && n&1){
            q.push_back(s[i++]);
        }
        if(i<n)
            q.push_front(s[i]);
        if(i+1 < n){
            q.push_back(s[++i]);
        }
    }

    while(!q.empty()){
        cout<<q.front();
        q.pop_front();
    }
    cout<<endl;
}

C

题意:给出标号为0~n的点,有往返于[0, n]之间的列车,给出人的起点和终点,列车的起点和方向,以及车和人的速度,问人到达终点的最短时间。

思路:不管人是怎么到达重点的,它到达的方式只有走到或者车到,那么就比较走到和时间,和能上车情况下车到的时间,取较小值就可以了。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e3+5;
int tp[maxn], tt[maxn];

int main()
{
    cin.sync_with_stdio(false);

    int s, x1, x2, t1, t2, p, d;

    cin>>s>>x1>>x2;
    cin>>t1>>t2;
    cin>>p>>d;

    int ans = abs(x2-x1)*t2;
    int timet;

    if(x1 > x2){
        x2 = s - x2;
        x1 = s - x1;
        p = s - p;
        d = -d;
    }
    if(d == -1){
        timet = p*t1 + x2*t1;
    }

    else if(p > x1){
        timet = (2*s-p+x2)*t1;
    }
    else {
        timet = (x2-p)*t1;
    }
    cout<<min(ans, timet)<<endl;
}

D

题意:有黑茶茶包和绿茶茶包若干,不能连续喝k杯以上相同的茶,问能否有一种排列喝完所有的茶,输出任意一种排列。

思路:有优先排多的那个,每次尽量多排,少的预留出来若干做分隔,构造

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;

int t[2*maxn];

int main()
{
    cin.sync_with_stdio(false);

    int n, k, a, b;
    bool flag = true;

    cin>>n>>k>>a>>b;
    if(a>b) {
        flag = false;  // a > b
        swap(a, b);
    }
    int d = b/k + (b%k==0?0:1);
    int cnt = 1;
    if(a < d-1) puts("NO");
    else{
        a -= d-1;
        int  p = 0;
        while(b > 0){

            if(b>k){
                t[p++] = k;
                b -= k;
            }
            else {
                t[p++] = b;
                b = 0;
            }

            if(a>=k-1 && cnt<d){
                t[p++] = k;
                a -= k-1;
            }
            else if(a>0  && cnt<d){
                t[p++] = a+1;
                a = 0;
            }
            else if(a==0 && cnt<d){
                t[p++] = 1;
            }
            else if(a>0 && cnt==d){
                t[p++] = a;
                a = 0;
            }
            cnt++;
        }

        for(int i=0; i<p; i++)
        {
            if((flag && i&1) || (!flag && !(i&1)))
            {
                for(int j=0; j<t[i]; j++)
                    putchar('G');
            }
            else{
                for(int j=0; j<t[i]; j++)
                    putchar('B');
            }
        }
        puts("");
    }
}

E

题意:给出已有的n张卡片,另有[1, m]的卡片可以进行一对一交换,问如何才能使得已有卡片中奇数的个数和偶数的个数相等,且交换次数最少。

思路:用set模拟已有卡片,先换重复的,之后对不等情况再进行调整,模拟过的。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5+5;

int a[maxn];
bool vis[maxn];
set<int >s;

int main()
{
    int n, m;
    int sum1 = 0, sum2 = 0, p1 = 1, p2 = 2, cnt = 0;   // 1-odd 2-even
    int maxx = 0;
    scanf("%d%d", &n, &m);

    memset(vis, false, sizeof vis);

    for(int i=0; i<n; i++){
        scanf("%d", &a[i]);
        if(!s.count(a[i])) {
            vis[i] = true;
            s.insert(a[i]);
            if(a[i]&1) sum1++;
            else sum2++;
        }
    }

    for(int i=0; i<n; i++){
        if(!vis[i]){
            if(sum1<=sum2){
                while(s.count(p1)){
                    p1 += 2;
                }
                s.insert(p1);
                maxx = max(p1, maxx);
                a[i] =  p1;
                sum1++;
                cnt++;
            }
            else {
                while(s.count(p2)){
                    p2 += 2;
                }
                s.insert(p2);
                maxx = max(p2, maxx);
                a[i] = p2;
                sum2++;
                cnt++;
            }
        }
    }
    int i = 0;
    while(sum1>sum2){
        for(; i<n; i++){
            if(a[i]&1 && vis[i]){
                s.erase(a[i]);
                while(s.count(p2)){
                    p2 += 2;
                }
                s.insert(p2);
                a[i] = p2;
                maxx = max(p2, maxx);
                sum2++;
                sum1--;
                cnt++;
                break;
            }
        }
    }
    while(sum2>sum1){
        for(; i<n; i++){
            if(!(a[i]&1) && vis[i]){
                s.erase(a[i]);
                while(s.count(p1)){
                    p1 += 2;
                }
                s.insert(p1);
                a[i] = p1;
                maxx = max(p1, maxx);
                sum1++;
                sum2--;
                cnt++;
                break;
            }
        }

    }

    if(maxx>m) puts("-1");
    else {
        printf("%d\n", cnt);
        for(int i=0; i<n; i++)
            printf("%d%c", a[i], i==n-1?'\n':' ');
    }

}