Educational Codeforces Round 105 (Rated for Div. 2)

A. ABC String

题目大意:

实质上就是括号匹配,只不过‘A’,‘B’,'C’三个字母,每个字母都只能带表一种括号。

思路:

在任何时刻右括号不能比左括号多,最后要刚好匹配即可。

AC Code

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
    {
    
    
		map<char,int>mapp;
        mapp.clear();
		string s;
		cin>>s;
        int len=s.length();
		mapp[s[0]]=1;
		mapp[s[len-1]]=-1;
		if(s[0]==s[len-1])
		    cout<<"NO"<<endl;
		else
        {
    
    
            int num0=0,num1=0,num2=0;
		    for(int i=0;i<len;i++)
            {
    
    
                if(mapp[s[i]]==1) num0++;
                else if(mapp[s[i]]==-1) num1++;
                else num2++;
            }
            if(num0==num1&&num2!=0) printf("NO\n");
            else if(num0<num1&&num0+num2!=num1) printf("NO\n");
            else if(num0>num1&&num0!=num1+num2) printf("NO\n");
            else
            {
    
    
                num2=0;
                if(num0<num1) num2=1;
                else if(num0>num1) num2=-1;
                int sum=0;
                for(int i=0;i<len;i++)
                {
    
    
                    if(mapp[s[i]]!=0) sum+=mapp[s[i]];
                    else sum+=num2;
                    if(sum<0) break;
                }
                if(sum<0) printf("NO\n");
                else printf("YES\n");
            }
	    }
    }
    //system("pause");
    return 0;
}


B. Berland Crossword

题目大意:

有一个n*n大小的正方形,你可以给边界的方块涂色,然后给你上下左右边界的黑色方块的数量,问是否可行。

思路:

当每个边界黑色方块的数量<=n-2时当然是可行的,放在除了4个角上的位置即可。不然的话,其实我们也只要枚举4个角上的情况即可。

AC Code

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        int n,a,b,c,d;
        scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
        if(a<=n-2&&b<=n-2&&c<=n-2&&d<=n-2) printf("YES\n");
        else
        {
    
    
            int flag=0;
            for(int i=0;i<=1;i++)
            {
    
    
                for(int j=0;j<=1;j++)
                {
    
    
                    for(int k=0;k<=1;k++)
                    {
    
    
                        for(int f=0;f<=1;f++)
                        {
    
    
                            flag=0;
                            int a1=a,b1=b,c1=c,d1=d;
                            if(i==1) a1--,d1--;
                            if(j==1) a1--,b1--;
                            if(k==1) b1--,c1--;
                            if(f==1) c1--,d1--;
                            if(a1>=0&&a1<=n-2&&b1>=0&&b1<=n-2&&c1>=0&&c1<=n-2&&d1>=0&&d1<=n-2)
                            {
    
    
                                flag=1;
                                break;
                            } 
                        }
                        if(flag==1) break;
                    }
                    if(flag==1) break;
                }
                if(flag==1) break;
            }
            if(flag==1) printf("YES\n");
            else printf("NO\n");
        }
    }
    //system("pause");
    return 0;
}

C. 1D Sokoban

题目大意:

给你n个箱子的位置,和m个特殊位置。最开始时位于0点,推箱子时只能向左或向右推,不能把箱子回拉或者越过箱子。问最多有多少箱子在特殊位置上。

思路:

原点左边的箱子只能往左推,源点右边的箱子只能往右推,所以很明显可以把大于0和小于0的箱子分成两个部分来做。那么贪心的想,我们肯定是要把一些箱子一直推,直到某个特殊位置上,然后剩下的箱子不变。这样的话我们遍历每个特殊位置即可,把特殊位置idx[i]之前的箱子推到idx[i]这个位置上为止,然后idx[i]之后的箱子位置不变,这个时候我们还需要知道推到这个特殊位置之后,这一段连续的箱子有几个是位于特殊位置上,看到这个数据范围,很容易想到用树状数组解决这个问题。

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N],c[N],d[N];
int num[N];
int n,m;
unordered_map<int,int>mapp;
int lowbit(int x)
{
    
    
    return x&(-x);
}
void update(int x,int y)
{
    
    
    for(int i=x;i<=1e9;i+=lowbit(i))
        mapp[i]+=y;
}
int getsum(int x)
{
    
    
    int ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
        ans+=mapp[i];
    return ans;
}
unordered_map<int,int>mp;
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        scanf("%d%d",&n,&m);
        int num1=0,num2=0,num3=0,num4=0;
        mapp.clear(),mp.clear();
        for(int i=1;i<=n;i++)
        {
    
    
            int x;
            scanf("%d",&x);
            if(x<0) a[++num1]=-1*x;
            else b[++num2]=x;
        }
        sort(a+1,a+1+num1);
        for(int i=1;i<=m;i++)
        {
    
    
            int x;
            scanf("%d",&x);
            if(x<0) c[++num3]=-1*x;
            else d[++num4]=x;
        }
        sort(c+1,c+1+num3);
        for(int i=1;i<=num2;i++)
            mp[b[i]]=1;
        for(int i=1;i<=num4+1;i++) num[i]=0;
        for(int i=num4;i>=1;i--) 
            if(mp[d[i]]) num[i]=num[i+1]+1;
            else num[i]=num[i+1];
        int sum=0;
        int maxn=0;
        int idx=1;
        for(int i=1;i<=num4;i++)
        {
    
    
            update(d[i],1);
            while(b[idx]<=d[i]&&idx<=num2) idx++;
            maxn=max(maxn,num[i+1]+getsum(d[i])-getsum(d[i]-idx+1));
        }
        sum=sum+maxn;
        mp.clear(),mapp.clear();
        for(int i=1;i<=num1;i++)
            mp[a[i]]=1;
        for(int i=1;i<=num3+1;i++) num[i]=0;
        for(int i=num3;i>=1;i--) 
            if(mp[c[i]]) num[i]=num[i+1]+1;
            else num[i]=num[i+1];
        maxn=0;
        idx=1;
        for(int i=1;i<=num3;i++)
        {
    
    
            update(c[i],1);
            while(a[idx]<=c[i]&&idx<=num1) idx++;
            maxn=max(maxn,num[i+1]+getsum(c[i])-getsum(c[i]-idx+1));
        }
        sum+=maxn;
        printf("%d\n",sum);
    }
    //system("pause");
    return 0;
}

D待补。。。。。。

猜你喜欢

转载自blog.csdn.net/Stevenwuxu/article/details/114298108