Codeforces Round #472 A-D

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

A. Tritonic Iridescence

题目链接:点击打开链接

题意:使用CMY对字符串进行填充,要求相邻的两个不能相同,如果有两种以上可行填充方法就输出“YES”否则输出“NO”。

思路:对每一个问号进行判定,最后的结果就是所有问号的可行方案数的乘积,当然可能会超出数据范围,因此只要大于2不再变大。此外, 还要判断是否有连续两个相同。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 105;
const int MOD = 1e9+7;
const int INF = 1e9+7;

char str[MAXN];
set<char> gg;
int n;

int main()
{
    //FSIO;
    while(cin>>n)
    {
        scanf(" %s",str+1);
        int flag = 0;
        int res = 0;
        for(int i=1;i<=n;++i)
        {
            if(str[i]=='?')
            {
                if(!res)    res=1;
                gg.clear();
                if(i>1&&str[i-1]!='?') gg.insert(str[i-1]);
                if(i<n&&str[i+1]!='?') gg.insert(str[i+1]);
                if(res>=2)  res = 3;
                else    res = res*(3-gg.size());
            }
            else if(i<n&&str[i]==str[i+1])   {flag=1; break;}
        }
        if(!flag&&res>=2) cout<<"Yes"<<endl;
        else    cout<<"No"<<endl;
    }
    return 0;
}



B. Mystical Mosaic

题目链接:点击打开链接

题意:给定一种操作,即对于某非空的正整数集合的集合R,C,对于R_i和C_i,填充网格中R_i行与C_i列相交点为黑色,且R和C中任意两集合互斥。对于某网格,如能从空白网格经这样的操作变成该网格则输出“Yes”,否则输出“No”。

思路:因为每一个点都要进行判定,不妨从左上角开始扫描,对于存在黑格的行进行扫描,取其中的所有为黑格的对应列,再对所有列往下逐行扫描,若这些列在某行存在黑格,则所有列都必须有才行。之后标记已经扫描过的行列以及格子,只要遇到已经标记的行列就不行,否则则行。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 55;
const int MOD = 1e9+7;
const int INF = 1e9+7;

char mapp[MAXN][MAXN];
int mkr[MAXN];
int mkc[MAXN];


int n, m;
int cntblack;

int walk(int x, int y)
{
    vector<int> tmpp;
    for(int t=y; t<=m; ++t)
        if(mapp[x][t]=='#')
        {
            if(!mkc[t])
            {
                mkc[t] = 1;
                mapp[x][t]='.';
                cntblack--;
                tmpp.push_back(t);
            }
            else    return 0;
        }


    vector<int> tomark;

    for(int j=x+1; j<=n; ++j)
    {
        int cnt = 0;
        for(int i=0;i<tmpp.size();++i)
        {
            if(mapp[j][tmpp[i]]=='#')
            {
                cnt++;
                if(!mkr[j])
                {
                    tomark.push_back(j);
                    mapp[j][tmpp[i]]='.';
                    cntblack--;
                }
                else    return 0;
            }
        }
        if(cnt&&cnt!=tmpp.size())    return 0;
    }
    for(int i=0; i<tomark.size(); ++i)
        mkr[tomark[i]] = 1;
    return 1;
}

int solve()
{
    memset(mkr,0,sizeof(mkr));
    memset(mkc,0,sizeof(mkc));
    for(int i=1; i<=n; ++i)
    {
        for(int j=1; j<=m; ++j)
        {
            if(mapp[i][j]=='#')
            {
                if(!mkr[i]&&!mkc[j])
                {
                    if(!walk(i,j))     return 0;
                }
                else    return 0;
                /*cout<<endl;
                for(int mi=1;mi<=n;++mi)
                {
                    for(int mj=1;mj<=m;++mj)
                        cout<<mapp[mi][mj];
                    cout<<endl;
                }*/
            }
        }
    }
    return 1;
}

int main()
{
    FSIO;
    while(cin>>n>>m)
    {
        cntblack = 0;
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=m; ++j)
            {
                cin>>mapp[i][j];
                if(mapp[i][j]=='#')
                    cntblack++;
            }
        if(solve()&&cntblack==0) cout<<"Yes"<<endl;
        else    cout<<"No"<<endl;
    }
    return 0;
}



C. Three-level Laser

题目链接:点击打开链接

题意:在含n个数字的升序序列E中,依次选择三个下标i,j,k,使得i<j<k,且E_i + U<=E_k,输出最大的(E_k - E_j) / (E_k - E_i)。

思路:对于某个E_i来说,要使得该商最大,j肯定为i+1,而k肯定是满足要求的最大下标。所以对序列E进行一次扫描判断每个i的最大对应k即可。最后遍历一遍E求最大该商。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 100005;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int n, U;
int engery[MAXN];
int matters[MAXN];

int main()
{
    //FSIO;
    while(scanf("%d%d",&n,&U)!=EOF)
    {
        for(int i=1;i<=n;++i)   scanf("%d",engery+i);
        double ans = -1;
        int cur = 1;
        memset(matters,-1,sizeof(matters));
        for(int i=1;i<=n;++i)
        {
            while(engery[i]-U>engery[cur]&&cur<=n)
            {
                matters[cur] = i-1;
                cur++;
            }
        }
        for(;cur<=n;++cur)  matters[cur] = n;
        /*for(int i=1;i<=n;++i)
            cout<<matters[i]<<" ";
        cout<<endl;*/
        for(int i=1;i+2<=n;++i)
        {
            if(matters[i]>i+1)
            {
                ans = max(ans, (double)(engery[matters[i]]-engery[i+1])/(double)(engery[matters[i]]-engery[i]));
            }
        }
        printf("%.10f\n",ans);
    }
    return 0;
}


D. Riverside Curio

题目链接:点击打开链接

题意:主角每天对河流水位进行标记,相同水位不重复标记。给定每天的在河流水位上的标记数,求最小的所有天的河流水位下的标记数之和。

思路:对于某天来说,水位下的标记数 = 总的标记数 - 1 - 河流水位上的标记数。

所以,只需要求最小的每天的标记数即可。而对于某天在水位上的标记数来说,总的标记数的最小值即该数 + 1,而相邻两天的标记总数最多加一个。所以只需按照上述规则进行贪心地求每天的最小标记数即可,最后对相邻两天差大于1的进行贪心地处理(即顺次递减)。最后遍历数组求和即可。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 100005;
const int MOD = 1e9+7;
const int INF = 1e9+7;

long long level[MAXN];
long long minlevel[MAXN];
long long n;

int main()
{
    FSIO;
    while(cin>>n)
    {
        for(long long i=1;i<=n;++i)
            cin>>level[i];
        minlevel[1] = 1;
        for(long long i=2;i<=n;++i)
        {
            if(minlevel[i-1]-1>=level[i])   minlevel[i] = minlevel[i-1];
            else
            {
                long long tmp = 1;
                while(minlevel[i-1]-1+tmp<level[i]) tmp++;
                minlevel[i] = minlevel[i-1]+tmp;
                for(long long j=0;j<tmp;++j)
                    minlevel[i-j] = minlevel[i]-j;
            }
        }
        for(int i=n;i>1;--i)
        {
            if(minlevel[i]-minlevel[i-1]>1)
                minlevel[i-1] = minlevel[i]-1;
        }
        /*for(long long i=1;i<=n;++i)
            cout<<minlevel[i]<<" ";
        cout<<endl;*/
        long long ans = 0;
        for(long long i=1;i<=n;++i)
            ans = ans + (minlevel[i]-1-level[i]);
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lfhase/article/details/79698417