Codeforces Round #555 (Div. 3) ABC1C2DE题解

比赛链接:

http://codeforces.com/contest/1157

A. Reachable Numbers

模拟,用个vis记录下是否被访问就可以了

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
ll n;
map<ll,int>ma;
int main()
{
    scanf("%lld",&n);
    int num=1;
    stack<ll>s;
    s.push(n);
    ma[n]=1;
    while(!s.empty())
    {
        ll t=s.top();
        s.pop();
        t++;
        while(t%10==0)
        {
            t/=10;
        }
        if(ma[t]==0)
        {
            ma[t]=1;
            s.push(t);
            num++;
        }
    }
    printf("%d\n",num);
	return 0;
}

B. Long Number 

模拟,找到第一个f(x)>x的数,然后遍历下去,直到f(x)<x的数为止。

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
char a[maxn];
int n;
int f[15];
int main()
{
    scanf("%d",&n);
    scanf("%s",a);
    for (int i=1;i<=9;i++)
    {
        scanf("%d",&f[i]);
    }
    int st=0,ok=1;
    while(a[st]>=(f[a[st]-'0']+'0')&&st<n)
    {
        st++;
    }
    while(a[st]<=(f[a[st]-'0']+'0')&&st<n)
    {

        a[st]=(f[a[st]-'0']+'0');st++;
    }
    printf("%s\n",a);
	return 0;
}

C1. Increasing Subsequence (easy version)

贪心,如果左右两个数都比之前的数大,则找两个中较小的,如果两个数都小于之前的数则跳出,否则找其中较大的一个。

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int n;
int a[maxn];
vector<char>ans;
int b[maxn];
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    b[0]=0;
    int num=0;
    int i=1,j=n;
    while(i<=j)
    {
        if(max(a[i],a[j])<b[num])
        {
            break;
        }
        if((a[i]<a[j]&&a[i]>b[num])||a[j]<b[num])
        {
            ans.push_back('L');
            b[++num]=a[i];
            i++;
        }
        else
        {
            ans.push_back('R');
            b[++num]=a[j];
            j--;
        }
    }
    printf("%d\n",ans.size());
    for (int i=0;i<ans.size();i++)
    {
        printf("%c",ans[i]);
    }
    printf("\n");
	return 0;
}

C2. Increasing Subsequence (hard version)

这个题在之前的基础上加了出现相同的数字,还是按上一题的贪心策略,只不过遇到相等的数字的时候只能连续选一边的,看看哪一边连续递增序列最长即可。

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int n;
int a[maxn];
vector<char>ans;
int b[maxn];
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    b[0]=0;
    int num=0;
    int i=1,j=n;
    int ok=0;
    while(i<=j)
    {
        if(max(a[i],a[j])<=b[num])
        {
            break;
        }
        if(a[i]==a[j]&&i!=j)
        {
            ok=1;
            break;
        }
        if((a[i]<a[j]&&a[i]>b[num])||a[j]<=b[num])
        {
            ans.push_back('L');
            b[++num]=a[i];
            i++;
        }
        else
        {
            ans.push_back('R');
            b[++num]=a[j];
            j--;
        }
    }
    if(ok)
    {
        int num1=0,num2=0;
        int ii=i,jj=j;
        int ti=b[num],tj=b[num];
        while(a[ii]>ti&&ii<j)
        {
            num1++;
            ti=a[ii];
            ii++;
        }
        while(a[jj]>tj&&jj>i)
        {
            num2++;
            tj=a[jj];
            jj--;
        }
        if(num1>num2)
        {
            for (int i=0;i<num1;i++) ans.push_back('L');
        }
        else
        {
            for (int i=0;i<num2;i++) ans.push_back('R');
        }
    }
    printf("%d\n",ans.size());
    for (int i=0;i<ans.size();i++)
    {
        printf("%c",ans[i]);
    }
    printf("\n");
	return 0;
}

D. N Problems During K Days

先判定是否大于等于最小的情况。

然后在最小的情况下均分k个数,即每个数加上(n-(k*(k+1)/2))%k,然后在贪心把n%k加到k个数中,从后面往前面贪,遇到后面的数小于前面数的2倍就加上数使其等于前一个的数的二倍,如果n%k消耗完则符合要求,如果消耗不完则输出NO

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
ll k;
ll n;
ll ans[maxn];
int main()
{
    scanf("%lld%lld",&n,&k);
    if(n<k*(1+k)/2)
    {
        printf("NO\n");
        return 0;
    }
    n-=k*(1+k)/2;
    ll t=n/k;
    n=n%k;
    for (int i=1;i<=k;i++)
    {
        ans[i]=i+t;
    }
    for (int i=k-1;i>=1;i--)
    {
        if(n==0) break;
        if(ans[i]*2>ans[i+1])
        {
            ll cha=2*ans[i]-ans[i+1];
            if(n>=cha)
            {
                ans[i+1]+=cha;
                n-=cha;
            }
            else
            {
                ans[i+1]+=n;
                n=0;
            }
        }
    }
    if(n==0)
    {
        printf("YES\n");
        for (int i=1;i<=k;i++) printf("%lld ",ans[i]);
        printf("\n");
    }
    else
    {
        printf("NO\n");
    }
	return 0;
}

E. Minimum Array

此题可以用mutliset容器来做,将所有的b[i]压入mutliset中,然后求出啊a[i]中的最优解,然后二分查找大于等于这个最优解的位置,如果没有找到的话,则直接用首部元素,因为这时候首部元素是最优解,找到之后再删除这个元素。

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD =  10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int n;
int a[maxn];
int b[maxn];
int ans[maxn];
multiset<int>st;
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);
        st.insert(b[i]);
    }
    for (int i=1;i<=n;i++)
    {
        multiset<int>::iterator it;
        int yu=(n-a[i])%n;
        it=st.lower_bound(yu);
        if(it==st.end())
        {
            it=st.begin();
            ans[i]=(a[i]+(*it))%n;
            st.erase(it);
        }
        else
        {
            ans[i]=(a[i]+(*it))%n;
            st.erase(it);
        }
    }
    for (int i=1;i<=n;i++)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89601911