Educational Codeforces Round 101 A~D

因为准备期末考试,漏了半个多月的cf没有打,现在回来补补,顺便找一下手感(好久没打,都生疏了QAQ)

A. Regular Bracket Sequence

题目传送门:

A. Regular Bracket Sequence

思路:

只有一对括号‘()’,剩下的全部都是问号,每个问号都有可能是‘(’或者是‘)’,问能不能使所有的括号匹配。
最开始没有看到只有一对括号的那个条件,还写复杂了。

AC Code

#include 
using namespace std;
string s;
int main()
{
     
   int t;
   cin>>t;
   while(t--)
   {
     
       cin>>s;
       int n=s.size();
       if(n&1||s[0]==')'||s[n-1]=='(')
        cout<<"NO"<<endl;
        else 
        cout<<"YES"<<endl;
   }
   return 0;
}

B. Red and Blue

题目传送门:

B. Red and Blue

思路:

因为r数组和b数组中的元素在a数组中的相对位置并没有改变,所以另r数组的最大前缀和为X,b数组的最大前缀和为Y,那么答案便是max( X , Y , X + Y )。

AC Code

#include
using namespace std;
int n,m;
int r[200],b[200];
int f1[200],f2[200];
int main()
{
     
    int t;
    scanf("%d",&t);
    while(t--)
    {
     
        memset(f1,0,sizeof(f1));
        memset(f2,0,sizeof(f2));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&r[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&b[i]);
        int maxr=-1e5,maxb=-1e5;
        for(int i=1;i<=n;i++)
        {
     
            f1[i]=f1[i-1]+r[i];
            maxr=max(maxr,f1[i]);
        }
        for(int i=1;i<=m;i++)
        {
     
            f2[i]=f2[i-1]+b[i];
            maxb=max(maxb,f2[i]);
        }
        int res=0;
        res=max(maxr,maxb);
        res=max(res,maxr+maxb);
        res=max(res,0);
        printf("%d\n",res);
    }
    //system("pause");
    return 0;
}

C. Building a Fence

题目传送门:

C. Building a Fence

思路:

第一个栅栏和最后一个栅栏的位置是肯定的。求出每个栅栏的起点区间,然后与前一个栅栏相比较有没有公共边即可。如果2~n-1个栅栏都满足,那么不要忘记和最后一个确定的栅栏相比较。

AC Code

#include
using namespace std;
const int N=2e5+10;
int h[N];
int top[N],low[N];
int main()
{
     
    int t;
    scanf("%d",&t);
    while(t--)
    {
     
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&h[i]);
        top[1]=h[1],low[1]=h[1];
        top[n]=h[n],low[n]=h[n];
        int flag=0;
        for(int i=2;i<n;i++)
        {
     
            top[i]=h[i]+k-1;//最高的起点
            low[i]=h[i];   //最低的起点
            top[i]=min(top[i],top[i-1]+k-1);
            low[i]=max(low[i],low[i-1]-k+1);
            if(low[i]>=top[i-1]+k||top[i]<=low[i-1]-k)
            {
     
                flag=1;
                break;
            }
        }
        if(low[n]>=top[n-1]+k||top[n]<=low[n-1]-k) flag=1;
        if(flag==1) printf("NO\n");
        else printf("YES\n");
    }
    //system("pause");
    return 0;
}

D. Ceil Divisions(构造)

题目传送门:

D. Ceil Divisions

思路:

我们发现一个比n小的数除以n向上取整之后都为1。但是这样最后会留下一个n无法处理。于是我们就想着n该怎么处理。我最开始想到的是不断除以2,但是看到数据范围和最大的操作数,这样想显然是不对的。看到这个操作数,那么感觉最可能的是开平方。然后我们观察(n^1/2,n) ,我们发现n除以两次前者即为1。而且2e5不断开平方为200000 448 22 5 3 2,显然操作的次数是满足题目要求的。

AC Code

#include
using namespace std;
const int N=2e5+10;
int h[N];
int top[N],low[N];
int main()
{
     
    int t;
    scanf("%d",&t);
    while(t--)
    {
     
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&h[i]);
        top[1]=h[1],low[1]=h[1];
        top[n]=h[n],low[n]=h[n];
        int flag=0;
        for(int i=2;i<n;i++)
        {
     
            top[i]=h[i]+k-1;//最高的起点
            low[i]=h[i];   //最低的起点
            top[i]=min(top[i],top[i-1]+k-1);
            low[i]=max(low[i],low[i-1]-k+1);
            if(low[i]>=top[i-1]+k||top[i]<=low[i-1]-k)
            {
     
                flag=1;
                break;
            }
        }
        if(low[n]>=top[n-1]+k||top[n]<=low[n-1]-k) flag=1;
        if(flag==1) printf("NO\n");
        else printf("YES\n");
    }
    //system("pause");
    return 0;
}

你可能感兴趣的:(Codeforces,算法)