Codeforces Round #605 (Div. 3)

本文深入解析了四道算法竞赛题目,包括寻找三人间最小移动距离、利用最少字符返回原点、匹配字符串中最多字符及求解严格单调上升子区间数量。采用排序、前缀和、动态规划等技术解决,提供了详细的思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题地址
A题意就是有三个人,每个人都只能移动一次或者不移动,问他们三个之间的距离最小是多少
思路:通过排序找出找出中间值,最小值和最大值,然后先判断其中是否有相等的存在,如果只有一个最大值(也就是其他两个相等)那么就是那两个数一起移动,只有一个最小值原理相同,否则就是最小值和最大值同时往中间移动

#include<bits/stdc++.h>
using namespace std;
#define ll long long

inline int read()
{
    int num=0,w=0;
    char ch=0;
    while(!isdigit(ch))
    {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch^48);
        ch=getchar();
    }
    return w?-num:num;
}

inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
ll arr[1000000];
ll brr[1000000];
ll crr[1000000];
ll dp[600000][2];
ll a[1000000];
int main()
{
   ll n =read();
   while(n--){
        ll a ,b ,c ,cnt =0;
        a =read(),b =read(),c =read();
        ll ma , mi, mid;

        ma =max(a,max(b,c));
        mi =min(a,min(b,c));
        mid = (a+b+c)-ma-mi;
      //  cout<<ma<<" "<<mid<<" "<<mi<<endl;
        if(mi==ma){
            cnt  =0 ;
        }
        else if(mid == ma ){
            cnt = (mid -  mi-2)*2;
        }
        else if(mid == mi){
            cnt =(ma-mid-2)*2;
        }
        else {
            cnt = (ma-mid-1)+(mid-mi-1)+(ma-mi-2);
           // cout<<(ma-mid-1)<< " "<<(mid-mi-1)<<" "<<(ma-mi-2)<<endl;
        }
        ll k =0 ;
        cout<<max(k,cnt)<<endl;

   }
    return 0;
}//8+

B题题意:问再给出一组字符串的情况下,最多能用多少字符(除了原点,其他不能走第二次)回到原点
思路:先把上下左右分为两组(上下一组,左右一组)

  1. 有一组里面不存在,那就只能是输出 2(这样才能回到原点)
  2. 如果都存在的话,就输出这两组中每组最少的那个方向数之和。(不然走不到原点)
  3. 否则输出0(肯定回不去原点了)
#include<bits/stdc++.h>
using namespace std;
#define ll long long

inline int read()
{
    int num=0,w=0;
    char ch=0;
    while(!isdigit(ch))
    {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch^48);
        ch=getchar();
    }
    return w?-num:num;
}

inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
ll arr[1000000];
ll brr[1000000];
ll crr[1000000];
int main()
{
    int  n   =read();
    while(n--)
    {
        string s ;
        cin >>s;
        map<char,int>mp;
        int len = s.size();
        // cout<<len<<endl;
        for(int i=0; i<len; i++)
        {
            if(mp[s[i]]==0)
                mp[s[i]] =1 ;
            else
                mp[s[i]]++;
        }
        if(mp['L']!=0&&mp['R']!=0&&mp['U']!=0&&mp['D']!=0)
        {
            cout<<min(mp['L'],mp['R'])*2+min(mp['U'],mp['D'])*2<<endl;
            for(int i=0; i<min(mp['L'],mp['R']); i++)
                cout<<"L";
            for(int i=0; i<min(mp['U'],mp['D']); i++)
                cout<<"U";
            for(int i=0; i<min(mp['L'],mp['R']); i++)
                cout<<"R";
            for(int i=0; i<min(mp['U'],mp['D']); i++)
                cout<<"D";
            cout<<endl;
        }
        else
        {
            if(mp['L']!=0&&mp['R']!=0&&(mp['U']==0||mp['D']==0))
            {
                cout<<2<<endl;
                cout<<"LR"<<endl;
            }
            else
            {
                if((mp['L']==0||mp['R']==0)&&mp['U']!=0&&mp['D']!=0)
                {
                    cout<<2<<endl;
                    cout<<"UD"<<endl;
                }
                    else
                        cout<<0<<endl;


            }
        }

        mp.clear();
    }
    return 0;
}

C题意:找出最多符合第二行字符的第一行字符最大数量
思路:前缀和,匹配的时候如果有不一样的就从1从头开始

#include<bits/stdc++.h>
using namespace std;
#define ll long long

inline int read()
{
    int num=0,w=0;
    char ch=0;
    while(!isdigit(ch))
    {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch^48);
        ch=getchar();
    }
    return w?-num:num;
}

inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
ll arr[1000000];
ll brr[1000000];
ll crr[1000000];
char ch[50];
int main()
{
    int n =read();
    int k =read();
    ll cnt =0 ;
    string s;cin >>s;ll si =0;
    for(int i=0; i<k; i++)
    {
        char cdh;cin  >>cdh;
        if(cdh!=' ')ch[si++]=cdh;
    }
    ll num =1 ;
    int f = k;
    for(int i=0; i<n; i++)
    {
        f = k;
        for(int j=0; j<si; j++)
        {
            if(s[i]==ch[j])
            {
                cnt+=num;
                num++;
                f -- ;
                break;
            }
        }
        if(f==k)num =1;//prime;
        //cout<<cnt<<endl;
    }
    cout<<cnt<<endl;

    return 0;
}//8+

D题题意找出每次只删一个字符的情况下,最多有多少严格单调上升子区间
思路:DP,分为两种情况

  1. 符合上升的子区间,
  2. 符合删除一个后上升的子区间,
    那么使用二维数组即可:一个存第一种情况,一个存第二种情况,最后找最大就行。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
 
inline int read()
{
    int num=0,w=0;
    char ch=0;
    while(!isdigit(ch))
    {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch^48);
        ch=getchar();
    }
    return w?-num:num;
}
 
inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
ll arr[1000000];
ll brr[1000000];
ll crr[1000000];
ll dp[600000][2];
ll a[1000000];
int main()
{
    ll n=read();
    for(ll i=1; i<=n; i++)
    {
        a[i] = read();
        dp[i][0] = 1;
        dp[i][1] = 1;
    }ll ma =0 ;
    for(ll i=2;i<=n;i++){
        if(a[i]>a[i-1]){
            dp[i][0] = dp[i-1][0]+1;
            dp[i][1] = dp[i-1][1]+1;
        }
        if(a[i]>a[i-2]){
            dp[i][1] = max(dp[i-2][0]+1,dp[i][1]);
        }
        ma = max(ma,max(dp[i][0],dp[i][1]));
    }
    cout<<ma<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值