Codeforces Round #656 (Div. 3)——A.B.C.(D-dfs)

Codeforces Round #656 (Div. 3)

A. Three Pairwise Maximums

题目描述
在这里插入图片描述
Example
input

5
3 2 3
100 100 100
50 49 49
10 30 20
1 1000000000 1000000000

output

YES
3 2 1
YES
100 100 100
NO
NO
YES
1 1 1000000000

题意:求一组a,b,c三个数,是满足max(a,b)=x,max(a,c)=y,max(b,c)=z,现在给出x,y,z。
思路

max的话可以相等;三个数比较的结果肯定最多只有两个不同的数

三个数之间比较有三种情况是满足条件的:
第一种前两个数相等且大于第三个数(即x=y&&y>z),那a,b,c可以是y,z,z(x取的是a的值,y取的是a的值,z取得是b,c中一个(相等));
第二种是第一个数和第三个数相等,且大于中间那个数(即x=z&&x>y),那a,b,c可以是y,x,y(x取的是b的值,z取的是b的值,y取得是a,c中一个(相等));
第三种是第二和第三个数相等,且大于第一个数(即y=z&&y>x),那a,b,c可以是x,x,z(x取的是a,b中的一个值(相等),y取的是c的值,z取的是c的值);
其他情况则不可能。
代码

#include <iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(x<=y&&y==z)
        {
            printf("YES\n");
            printf("%d %d %d\n",x,x,z);
        }
        else if(x==y&&y>=z)
        {
            printf("YES\n");
            printf("%d %d %d\n",y,z,z);
        }
        else if(x==z&&x>=y)
        {
            printf("YES\n");
            printf("%d %d %d\n",y,x,y);
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}

B. Restore the Permutation by Merger

题目描述

在这里插入图片描述
Example
input

5
2
1 1 2 2
4
1 3 1 4 3 4 2 2
5
1 2 1 2 3 4 3 5 4 5
3
1 2 3 1 2 3
4
2 3 2 4 1 3 4 1

output

1 2 
1 3 4 2 
1 2 3 4 5 
1 2 3 
2 3 4 1 

题意:一个2*n长的数组,由两个相同的数组组成,一个数组插入另一个数组,混合后的数组的在原数组中的顺序不发生变化,给你混合后的数组,求数组。
思路:观察样例发现第一次出现新数值,就需要记录,即在原数组出现的顺序。

#include <iostream>
#include<map>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,a[200],b[100];
        scanf("%d",&n);
        for(int i=0; i<2*n; i++)
            scanf("%d",&a[i]);
        map<int,int>cnt;
        int  k=0;
        for(int i=0; i<2*n; i++)
        {
            if(cnt[a[i]]==0)
            {
                cnt[a[i]]++;
                b[k++]=a[i];
            }
        }
        for(int i=0; i<n; i++)
            printf("%d ",b[i]);
        printf("\n");
    }
    return 0;
}

C. Make It Good

题目描述
在这里插入图片描述
Example
input

5
4
1 2 3 4
7
4 3 3 8 4 5 2
3
1 1 1
7
1 3 1 4 5 3 2
5
5 4 3 2 3

output

0
4
0
2
3

题意:就是给一个a让从头删去一定的长度的数组,剩余部分,从头或从尾一次去一个,取出全部剩下的数组,构成的数组c是一个非递减数组。思路:从头删元素,那就表示剩下的部分,中间高两边小,像一个山峰的数值排列。那就变成从后面开始找到峰值(flag标记找到峰值),再找到过了峰值后再变高位置,这个位置及这个位置之前全部删掉。
代码

#include <iostream>
#include<map>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,a[200005];
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        int  r=n,flag=0,i;
        for(i=n-1; i>0; i--)
        {
            if(flag==1&&a[i]>a[i+1])
            {
                break;
            }
            if(a[i]<a[i+1]&&flag==0)
                flag=1;
        }
        printf("%d\n",i);
    }
    return 0;
}

D. a-Good String

题目描述
在这里插入图片描述
Example
input

6
8
bbdcaaaa
8
asdfghjk
8
ceaaaabb
8
bbaaddcc
1
z
2
ac

output

0
7
4
5
1
1

题意:给你一个字符串,求出题目中定义的好的字符串,即字符串的一般是一个字符,一半的一半是一个字符,一半的一半是一个字符,一直下去剩两个不同的字符。(保证n=2k,n为偶数)。
思路:自己没有想到,看了别人的代码之后略有了些许浅薄的了解,以下,利用dfs来找每分成两半,利用两半每半的需要变化的值+剩下另一半继续dfs,知道只剩一个字符,及走到了左右为相同的位置。相当于(dfs每次行动都有两个方向,要左半面还是右半面)。
代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=131100;
char s[maxn];
int sum=0;
int dfs(int l,int r,char ch)
{
    if(l==r)
    {
        if(s[l]!=ch)
            return 1;
        else
            return 0;
    }
    int mid=(l+r)/2,ln=0,rn=0;
    for(int i=l; i<=mid; i++)
    {
        if(s[i]!=ch)
            ln++;
    }
    for(int i=mid+1; i<=r; i++)
    {
        if(s[i]!=ch)
            rn++;
    }
    ch++;
    sum=min(ln+dfs(mid+1,r,ch),rn+dfs(l,mid,ch));
    return sum;
}
int main ()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        cin>>s;
        char tmp='a';
        printf("%d\n",dfs(0,n-1,tmp));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值