Codeforces Round #615(Div.3)解题报告

Codeforces Round #615(Div.3)解题报告

A. Collecting Coins

注意\(n\)可能不够用的情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, b, c, n;
void solve()
{
    cin >> a >> b >> c >> n;
    int mx = max(max(a, b), c);
    int mi = min(min(a, b), c);
    int s = a+b+c;
    int m = s - mx - mi;
    n -= (mx - mi);
    n -= (mx - m);
    if(n < 0){
        puts("NO");
        return;
    }
    if(n % 3 == 0) puts("YES");
    else puts("NO");
}

int main()
{
    int T = 1;
    scanf("%d", &T);
    while(T--) solve();
    return 0;
}

B. Collecting Packages

直接模拟这个过程就好了,注意字典序最小的方案。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 10;
int n;
//只能上和右

struct Node{
    int x, y;
}p[maxn];

bool cmp(Node a, Node b){
    if(a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

void solve()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d%d", &p[i].x, &p[i].y);
    sort(p+1, p+1+n, cmp);

    for(int i = 1; i < n; i++)
    {
        if(p[i].y > p[i+1].y && p[i].x != p[i+1].x)
        {
            puts("NO");
            return;
        }
    }
    puts("YES");
    string ans = "";
    for(int i = 0; i < n; i++)
    {
        int x1 = p[i].x, y1 = p[i].y;
        int x2 = p[i+1].x, y2 = p[i+1].y;
        int d1 = x2 - x1;
        int d2 = y2 - y1;
        while(d1) ans += 'R', d1--;
        while(d2) ans += 'U', d2--;
    }
    cout << ans << endl;
}

int main()
{
    int T = 1;
    scanf("%d", &T);
    while(T--) solve();
    return 0;
}

C. Product of Three Numbers

枚举因数,看看能不能成。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
    int n; cin >> n;
    vector<int> ans;
    int t = n;
    for(int i = 2; i <= n/i; i++)
    {
        if(t % i == 0)
        {
            ans.push_back(i);
            t = t / i;
        }
        if(t == 1) break;
    }

    if(ans.size() == 1 || ans.size() == 0)
    {
        puts("NO");
        return;
    }

    if(ans.size() == 2)
    {
        int t = ans[0]*ans[1];
        if(n % t == 0 && n/t != ans[0] && n/t != ans[1])
        {
            puts("YES");
            printf("%d %d %d\n", ans[0], ans[1], n/t);
            return;
        }
        else
        {
            puts("NO");
            return;
        }
    }
    puts("YES");
    int t1 = ans[0], t2 = ans[1];
    int t3 = n/(t1*t2);
    printf("%d %d %d\n", t1, t2, t3);

}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--) solve();
    return 0;
}

D. MEX maximizing

根据贪心的思路我们可以发现答案一定是递增的,所以我们就直接把所有的点都减到不能减为止,然后答案可以变大的时候用他们来做贡献。

其实可以不用\(unordered\_map\),可以直接用数组来维护一下...

#include<bits/stdc++.h>
using namespace std;
const int maxn = 4e5 + 10;
int q, x;
int main()
{
    scanf("%d%d", &q, &x);
    vector<int> a;
    unordered_map<int, int> mp;
    int ans = 0;
    while(q--)
    {
        int num;
        scanf("%d", &num);
        mp[num % x]++;
        while(mp[ans]) ans++;
        while(mp[ans%x] > 1)
        {
            mp[ans%x]--;
            ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

E. Obtain a Permutation

题意也就是用最少的操作次数使得矩阵每个元素\(a(i,j)=(i-1)m+j\)。

分析一下的话可以发现,每一列其实是独立的,所以最终答案一定是每一列的答案相加。

考虑第\(j\)列,最终第\(j\)列的元素就为\(j,j+m,j+2m,...,j+(n-1)m\)。

对于给出的第\(j\)列数字,可以枚举谁作为最高位,从而来计算答案。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
vector<int> a[maxn], b[maxn];
int n, m;
int vis[maxn], add[maxn<<1];
int main()
{
    scanf("%d%d", &n, &m);
    int cnt = 0;
    for(int i = 1; i <= n; i++)
    {
        a[i].resize(m+1);
        b[i].resize(m+1);
        for(int j = 1; j <= m; j++)
        {
            scanf("%d", &a[i][j]);
            b[i][j] = ++cnt;
        }
    }

    long long ans = 0;
    for(int j = 1; j <= m; j++)
    {
        for(int i = 1; i <= n; i++) vis[b[i][j]] = i;
        for(int i = 1; i <= n; i++)
        {
            if(vis[a[i][j]]) //如果这个数本应该属于这个序列中
            {
                int t = vis[a[i][j]];
                if(t == i) add[1]++, add[n+1]++; //正好在位置上
                //放到该放到的位置上
                else if(i > t) add[1+i-t]++;
                else add[1+n+i-t]++;
            }
        }
        int tmp = 0, mi = n;
        //枚举开头的位置
        for(int l = 1; l <= n; l++)
        {
            tmp = add[l];
            //tmp 不需要变化的元素
            //本次需要的操作=n-不需要变化的元素+把它们shift到最高位
            mi = min(mi, n-tmp+(l-1));
        } ans += mi;
        for(int i = 1; i <= 2*n; i++) add[i] = 0;
        for(int i = 1; i <= n; i++) vis[b[i][j]] = 0;
    } cout << ans << endl;
    return 0;
}

F. Three Paths on a Tree

首先可以确定的是,其中的两个点一定在直径的两个端点上。

第三个点要怎么确定呢?

设\(len(a,b)\)表示\(a\)到\(b\)的距离,那么答案就是\(\frac{len(a,b)+len(b,c)+len(a,c)}{2}\)。

所以我们找\(len(a,c)+len(b,c)\)最大就行了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n;
int head[maxn], nex[maxn<<1], ver[maxn<<1], edge[maxn<<1], tot;
inline void add_edge(int x, int y){
    ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
    edge[tot] = 1;
}

int vis[maxn];
int sum[maxn];
int bfs(int x)
{
    memset(vis, 0, sizeof(vis));
    queue<int> q;
    q.push(x);
    int t;
    while(q.size())
    {
        t = q.front(); q.pop();
        for(int i = head[t]; i; i = nex[i])
        {
            int y = ver[i];
            if(!vis[y] && y != x)
            {
                q.push(y);
                vis[y] = vis[t] + 1;
            }
        }
    } return t; //bfs两段性保证t最远
}

int main()
{
    scanf("%d", &n);
    for(int i = 1, x, y; i <= n-1; i++)
    {
        scanf("%d%d", &x, &y);
        add_edge(x, y); add_edge(y, x);
    }

    int x = bfs(1), y = bfs(x), ans = 0, z;
    //此时的vis数组中存着每个点离x的距离
    //sum数组中存着len(x,y)+len(x,i)
    for(int i = 1; i <= n; i++)
        sum[i] = vis[y] + vis[i];
    bfs(y); //vis数组中存着每个点离y的距离
    for(int i = 1; i <= n; i++)
    {
        //sum中存着len(x,y)+len(x,i)+len(y,i)
        sum[i] += vis[i];
        if(i != x && i != y && sum[i] > ans)
        {
            ans = sum[i];
            z = i;
        }
    }
    printf("%d\n%d %d %d\n", ans/2, x, y, z);
    return 0;
}

原文地址:https://www.cnblogs.com/zxytxdy/p/12236772.html

时间: 2024-08-08 09:38:26

Codeforces Round #615(Div.3)解题报告的相关文章

Codeforces Round #259 (Div. 2) 解题报告

终于重上DIV1了.... A:在正方形中输出一个菱形 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月01日 星期五 23时27分55秒 4 5 #include<vector> 6 #include<set> 7 #include<deque> 8 #include<stack> 9 #include<bitset> 10 #inclu

Codeforces Round #262 (Div. 2)解题报告

详见:http://robotcator.logdown.com/posts/221514-codeforces-round-262-div-2 1:A. Vasya and Socks   http://codeforces.com/contest/460/problem/A 有n双袜子,每天穿一双然后扔掉,每隔m天买一双新袜子,问最多少天后没有袜子穿.. 简单思维题:以前不注重这方面的训练,结果做了比较久,这种题自己边模拟边想.不过要多考虑trick ```c++ int main(){ i

Codeforces Round #616 (Div. 2)解题报告

Codeforces Round #616 (Div. 2)解题报告 A. Even But Not Even 找两个奇数就行了. #include<bits/stdc++.h> using namespace std; void solve() { int n; string s; cin >> n >> s; string ans = ""; for(int i = 0; i < n; i++) { if(int(s[i] - '0')%2

Codeforces Round #479 (Div. 3)解题报告

题目链接: http://codeforces.com/contest/977 A. Wrong Subtraction 题意 给定一个数x,求n次操作输出.操作规则:10的倍数则除10,否则减1 直接写,手速题,没啥好说的 B. Two-gram 题意 求出现次数最多的连续两个字符 还是签到题,我居然很麻烦地用了map,= =算了,思路畅通都无所谓了 #include <iostream> #include<stdio.h> #include<algorithm> #

Codeforces Round #515 (Div. 3) 解题报告(A~E)

题目链接:http://codeforces.com/contest/1066 A题: 题意:Vova想坐火车从1点到L点,在路上v的整数倍的点上分布着灯笼,而在路上从l到r处停着别的火车,它挡着Vova的视线使他看不到灯笼.给定L,v,l,r求Vova能看到的灯笼数. 分析:从1到x上所有的灯笼数量为x/v个.则路上所有的灯笼数为L/v个,被挡住的则为 r/v - (l-1)/v 个,相减即为答案. #include<iostream> #include<cstdio> #inc

Codeforces Round #401 (Div. 2)解题报告

A - Shell Game 1 #include <iostream> 2 #include<bits/stdc++.h> 3 #include <stack> 4 #include <queue> 5 #include <map> 6 #include <set> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10

Codeforces Round #390 (Div. 2) 解题报告

时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing383简直人生巅峰…… 看楼上楼下都是两道题的 如果A题不错那么多估计能进前300了吧…… 这场倒是把之前两场的分加回来了 开头不错 这个假期争取紫名~ A.Lesha and array splitting 把给定的数组分割成几个区间 要求各个区间和不能为0 一开始没注意到分割之后的区间重新合成之

Codeforces Round #394 (Div. 2) 解题报告

开始补题,今天下午virtual参赛,过了ABC,D题因为一点小错误而没能在比赛时间中AC,时间到了之后几分钟就发现了问题所在,略有遗憾.之后一直冥思苦想E题,在提示下终于明白,真的是给这样组合题画风的题目跪了,只能说继续加油,扩展思路吧. A题 题目地址 只有奇偶数个数相差小于等于1时可以,需要特判不能使二者均为0的情况. 参考代码 1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream>

Codeforces Round #279 (Div. 2) 解题报告

A - Team Olympiad 贪心水题..都从第一个开始取即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map

Codeforces Round #395 (Div. 2) 解题报告

年后恢复训练参加的第一场,表现的不是很好,必须要赶紧振作起来了啊. A.B题不再赘述. C题 不要被树的形式吓到,实际上不需要换根DFS,只需要看两顶点颜色不同的线段即可. 1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream> 4 using namespace std; 5 typedef long long ll; 6 typedef unsigned long long ull; 7