Codeforces Round #335 (Div. 2) [补E]

来源:互联网 发布:全炫茂 知乎 编辑:程序博客网 时间:2024/06/05 16:21

A. Magic Spheres

题意:有三种颜色的球a b c个,而需要的三种球的数量分别为x y z;并且,两个颜色相同的球可以换一个其他颜色的球,问是否能满足需求;

思路:对于有剩余的球,算其能换多少个其他颜色的球,然后看数量和能否满足不足的小球;


#include<bits/stdc++.h>int a, b, c;int x, y, z;int main(){scanf("%d%d%d", &a, &b, &c);scanf("%d%d%d", &x, &y, &z);int aa = a-x;int bb = b-y;int cc = c-z;if(aa >= 0 && bb >= 0 && cc >= 0){printf("Yes\n");return 0;}if(aa>=0)aa/=2;if(bb>=0)bb/=2;if(cc>=0)cc/=2;int k = aa+bb+cc;if(k>=0)printf("Yes\n");elseprintf("No\n");return 0;}




B. Testing Robots

题意:给定x*y的矩形,机器人的初始位置为(x0, y0),给出一串字符操作,如果越界就直接不动。当机器人走到矿山的地方,矿山就会爆炸;所有操作执行完后剩余的矿山都爆炸;问每次操作矿山爆炸的数量;矿山遍布整个矩形;

思路:对每个格子判断是否访问过即可,如果没访问过,爆炸数就是1;访问过了,爆炸数就是0;最后的操作算个差值;


#include<bits/stdc++.h>const int maxn = 1e5+5;bool vis[510][510];char s[maxn];int n, m, x, y;int ans[maxn];int main(){    memset(vis, false, sizeof vis);    scanf("%d%d%d%d", &n, &m, &x, &y);    scanf("%s", s);    vis[x][y] = true;    int cnt = 0;    int sum = 1;    ans[++cnt] = 1;    int a = x, b = y;    for(int i = 0;i<strlen(s)-1;i++)    {        int na = a, nb = b;        if(s[i] == 'U')            a--;        if(s[i] == 'D')            a++;        if(s[i] == 'L')            b--;        if(s[i] == 'R')            b++;        if(a<1 || b<1 || a>n || b>m)                a = na, b = nb;        if(vis[a][b])            ans[++cnt] = 0;        if(!vis[a][b])        {            vis[a][b] = true;            ans[++cnt] = 1;            sum++;        }    }    ans[++cnt] = n*m-sum;    for(int i = 1;i<=cnt;i++)    {        if(i == cnt)        printf("%d\n", ans[i]);        else        printf("%d ", ans[i]);    }    return 0;}




C. Sorting Railway Cars

题意:给出n个数,1~n,每次操作可以将其中一个数放到最前或者最后,直到数列呈递增排列,问至少需要几次操作;

思路:因为每次只能放到最前或最后,所以我们只需计算最长的呈现递增(相邻相差1)的序列,所求答案就是n-max;


#include<bits/stdc++.h>using namespace std;const int maxn = 1e5+5;int n;int a[maxn];int dp[maxn];bool vis[maxn];int main(){    memset(vis, false, sizeof vis);    scanf("%d", &n);    for(int i = 1;i<=n;i++)        dp[i] = 1;    for(int i = 1;i<=n;i++)    {        scanf("%d", &a[i]);        vis[a[i]] = true;        int k = a[i]-1;        if(vis[k])        dp[a[i]] += dp[k];    }    int maxx = dp[1];    for(int i = 1;i<=n;i++)    maxx = max(maxx, dp[i]);    printf("%d\n", n-maxx);    return 0;}




D. Lazy Student

题意:有n个点,m条边;下面m行,表示每条边的权重,以及该条边是否在最小生成树中(1是在,0是不在);问是否有图能满足上述情况。若有,输出每条边(与输入的边一一对应);若没有,输出-1;

思路:根据最小生成树原理,我们可以知道每次选取边时都是优先边权最小的,所以我们先将输入的边按权重小、存在树中进行排序。对于存在的边,我们直接按链式进行构造;对于不存在的边,我们构造环(不要有重边和自环),如果找不到可以构造的环就false;


#include<bits/stdc++.h>using namespace std;const int maxn = 1e5+5;int n, m;int from[maxn], to[maxn];struct node{    int w, flag, id;        bool operator < (const node& a)const    {        if(w != a.w)    return w<a.w;        return flag>a.flag;    }}edge[maxn];bool solve(){    int cnt = 1;    int u = 1, v = 3;    for(int i = 1;i<=m;i++)    {        int t = edge[i].id;        if(edge[i].flag)        {            from[t] = cnt;            to[t] = ++cnt;        }        else        {            if(v > cnt) return false;            from[t] = u;            to[t] = v;            u--;            if(u == 0)            {                v++;                u = v-2;            }        }    }    return true;}int main(){    scanf("%d%d", &n, &m);    for(int i = 1;i<=m;i++)    {        scanf("%d%d", &edge[i].w, &edge[i].flag);        edge[i].id = i;    }    sort(edge+1, edge+m+1);    if(solve())    {        for(int i = 1;i<=m;i++)            printf("%d %d\n", from[i], to[i]);    }    else    printf("-1\n");    return 0;}




E. Freelancer's Dreams








0 0