Codeforces Round #501 (Div. 3)前4题题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/suxuyu01/article/details/81323414

A. Points in Segments

这里写图片描述

Examples
input
3 5
2 2
1 2
5 5
output
2
3 4
input
1 7
1 7
output
0

直接暴力模拟,O(n^2)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstdlib>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int n,m;
bool line[101];
int main()
{

    queue<int> ans;
    int tx,ty;
    scanf("%d %d",&n,&m);
    For(i,1,n)
    {
        scanf("%d %d",&tx,&ty);
        For(j,tx,ty)
         line[j]=1;
    }
    For(i,1,m)
     if(!line[i])
        ans.push(i);
    cout<<ans.size()<<"\n";
    while(!ans.empty())
    {
        cout<<ans.front()<<" ";
        ans.pop();
    }
    return 0;
}

B. Obtaining the String

这里写图片描述
Examples
input
6
abcdef
abdfec

output
4
3 5 4 5

input
4
abcd
accd

output
-1

不要求步数最小就比较好办了(一开始只看到minimize还以为是个dp之类的,回头才看到do not have to,还是要多审审题啊。。。)
把t中的字符和s中的一个个匹配,按t中的序号给s中的赋值,做成一个数列
然后冒泡排序即可
依然是O(n^2) 。。。
这题一开始想的差不多,但没想转成序号的数列之后再冒泡排序,直接用字母一个一个比对,所以耽误了很长时间。。。
所以说,Think Twice , Code Once ,这句话我执行的还是不够彻底

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstdlib>
#define For(i,l,r) for(int i=l;i<=r;++i)

using namespace std;
int n,scnt[27],tcnt[27],sd[60],td[60];
char s[60],t[60];
int main()
{
    queue<int> ans;
    scanf("%d",&n);
    For(i,1,n)
    {
        while((s[i]=getchar())==' '||s[i]=='\n'||s[i]=='\r');
        scnt[s[i]-'a'+1]++;
    }
    For(i,1,n)
    {
        while((t[i]=getchar())==' '||t[i]=='\n'||t[i]=='\r');
        tcnt[t[i]-'a'+1]++;
    }
    For(i,1,26)
    {
        if(scnt[i]!=tcnt[i])
        {
            cout<<"-1";
            return 0;
        }
    }
    For(i,1,n)
    {
        td[i]=i;
        For(j,1,n)
        {
            if(s[j]==t[i]&&!sd[j])
            {
                sd[j]=i;
                break;
            }
        }
    }
    For(i,1,n)
    {
        For(j,1,n-1)
        {
            if(sd[j]>sd[j+1])
            {
                ans.push(j);
                swap(sd[j],sd[j+1]);
            }
        }
    }
    cout<<ans.size()<<'\n';
    while(!ans.empty())
    {
        cout<<ans.front()<<" ";
        ans.pop();
    }
}

C. Songs Compression

这里写图片描述
Examples
input
4 21
10 8
7 4
3 1
5 4

output
2

input
4 16
10 8
7 4
3 1
5 4

output
-1

分情况,先特判不可能全部装下和不需要压缩以及全部压缩(也不一定,可能有压缩前和压缩后占用空间相等的,这也是个小细节,这里所说的全部压缩是指粗略的全部压缩)之后恰好能装下的情况
如果不属于以上三种情况,那就按压缩前和压缩后的占用空间的差值排序,然后贪心就行了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#define For(i,l,r) for(int i=l;i<=r;++i)
#define MAXN 100001
using namespace std;
long long as,bs;
int n,m,song[MAXN];
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int tx,ty,tn;
    scanf("%d %d",&n,&m);
    tn=n;
    For(i,1,n)
    {
        scanf("%d %d",&tx,&ty);
        if(tx==ty)
            --tn;
        song[i]=tx-ty;
        as+=tx;
        bs+=ty;
    }
    if(as<=m)//无需压缩
    {
        cout<<"0";
        return 0;
    }
    if(bs>m)//不可能全装下
    {
        cout<<"-1";
        return 0;
    }
    if(bs==m)//全压缩恰好全装下
    {
        cout<<tn;
        return 0;
    }
    sort(song+1,song+n+1,cmp);
    bs=0;//使用bs记录答案
    For(i,1,n)
    {
        bs++;
        as-=song[i];
        if(as<=m)
         break;
    }
    cout<<bs;
    return 0;
}

D. Walking Between Houses

这里写图片描述

Examples
input
10 2 15

output
YES
10 4

input
10 9 45

output
YES
10 1 10 1 2 1 2 1 6

input
10 9 81

output
YES
10 1 10 1 10 1 10 1 10

input
10 9 82

output
NO

开始做这题的时候还剩25分钟左右
真的感觉A不掉了
结果最后10s交上然后A了23333
这题也算一个贪心吧
首先有两种情况是不能实现的

1.剩余(就是从第一步开始,但是这样说概括比较广泛)的平均每步要走的距离>(n-1)
2.s<k,即平均每步要走的距离不到1

特判这两种情况输出”NO”
否则就输出”YES”
然后就是怎么走的问题了
(突然感觉CF的评测机制很优秀啊,没有限定什么字典序最小之类的,但是长此以往怕是NOIp要爆零啊。。。)
每步走剩下步数每步平均要走的距离上取整
具体每一步怎么走呢
我们肯定是希望当前位置可以到达的距离远一些,不希望当前位置居中
那我们就先判断在左半区间还是右半区间,优先向靠边的方向走
然后就是判断能不能走了,一直这样循环即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

#define For(i,l,r) for(int i=l;i<=r;++i)

using namespace std;
int n,k;
long long s;
int main()
{
    long long temp;
    cin>>n>>k>>s;
    temp=ceil((double)(s/(double)k));
    if(temp>n-1||s<k)
    {
        cout<<"NO";
        return 0;
    }
    cout<<"YES\n";
    int now=1;
    For(i,1,k)
    {
        temp=ceil((double)(s/(double)(k-i+1)));
        //cout<<temp<<'a'<<'\n';
        s-=temp;
        if(now<=n/2&&now-temp>0)
        {
            now-=temp;
            cout<<now<<" ";
            continue;
        }
        if(now+temp<=n)
        {
            now+=temp;
            cout<<now<<" ";
            continue;
        }
        now-=temp;
        cout<<now<<" ";
    }
    //system("pause");
    return 0;
}

最后总结一下打这次比赛的历程吧
人生第一场CodeForces比赛o.o,虽然只A掉了四道题,但还是挺开心的

A题送分题所以直接就A掉了。。。
其实B一开始用字符直接比对没调出来我就有点慌了,然后去喝了杯水,突然想起来了这样冒泡排序。。。果然水是生命之源啊。。。交了4遍才A。。。真的慌。。。
C一开始也没有列举出来全部情况,交了两遍才A掉。。。
D题最后3分钟一直调试。。。差点就想放弃了。。。慌的不行。。。没想到居然能调出来,放平时估计放弃了。。。
打比赛真的和平时做题不太一样。。。打比赛有一种紧张刺激的畅快感。。。
当然NOIp当然不能在最后3分钟再去调试了。。。最后十分钟大概检查一下就完了吧。。。
不知道NOIp会多大难度。。。还是有点慌。。。
还是多打点比赛积累一下经验吧。。。
其实这场比赛好像我什么算法也没有用。。。

然后,以后写题之前还是要先多想一下再去打代码,比如在纸上列举列举什么的,说不定会事半功倍之类的。。。像B题写出来之后又去重构主体部分就很费时间。。。文化课也是这样吧。。。

最后,答疑好评!
这里写图片描述

猜你喜欢

转载自blog.csdn.net/suxuyu01/article/details/81323414