Codeforces Global Round 10(ABCD题解)

					A. Omkar and Password

.
在这里插入图片描述

在这里插入图片描述
题意:
给你一个长度为n的数组,你每次可以选择两个相邻的不相等的数把它们变成他俩的和,如 [ 1 2 3 4 ] ,你可以选择 2 ,3 。 然后把他俩合并成5,原序列变为 [ 1 5 4 ] 。
问你在进行任意多次操作后,原数组最少剩下几个数。
思路:
情况1:如果原数组只有一种数,答案是n。
情况2:否则答案是1.
简单证明:
情况一无需证明。
情况二: 你可以每次选择一个最大的数,让他变得更大,一直下去,最后就会只剩一个数。

				B. Omkar and Infinity Clock

.
在这里插入图片描述
在这里插入图片描述
题意:
给你一个长度为n的数组和一个数k,然后定义了一种修改操作,每次修改操作都是用当前数组中的最大值去更新该数组,更新公式是a[i]=该数组中的最大值 - a[i] 。问你进行k次操作后该数组会变成什么样子。
思路:
手写几下会发现一个性质,该数组除去初始形态后只有两种状态,对标每个a[i]就是max-a[i] , a[i]-min 这两个数中来回切换,自己推一推也很好证明。
然后就是把k取余2,直接输出答案就行。

.

					C. Omkar and Waterslide

.
在这里插入图片描述

在这里插入图片描述

题意:
给你一个长度为n的数组,你每次可以选择一段连续的非递减的序列,把他们都加1,问你最少要几次操作,使得这个序列整体变成非递减序列。
思路:
贪心+思维。
这个题倒着想会简单一些,倒着想的话很容易发现:
如果当前a[i]<a[i-1],ans+= a[i-1]-a[i] ;这样写的话,ans就是最终答案。
我不会证明。。。 但是这样应该很好想到。。。
吐槽:
刚开始理解错题意,以为每次只能加一个数,那样的话可以用rmq写。有兴趣的可以试试。

.

					D. Omkar and Bed Wars

.

在这里插入图片描述

在这里插入图片描述

题意:(白嫖群友一波题意。)
有n个人排成一个圈
每个人要么向左攻击要么向右攻击
他们需要满足一下的条件:
如果一个玩家正被另外一个玩家攻击,那么他应该打回去
如果一个玩家被0个或2个其他玩家攻击,那么他往左或往右打都行
你可以花费一次代价修改一个人的攻击方向 问最后满足条件的最小修改代价

思路:
有两种写法(我只会两种。。。)
第一种是dp,dp [len] [i] [j] [ii] [jj] 含义是长度为len的第一个人攻击方向是i,第二个人攻击方向是j,倒数第二个人攻击方向是ii,倒数第一个人攻击方向是jj。 然后状态转移就可以了,具体过程看代码。
第二种是找规律,手写一些样例发现 连续三个人的攻击方向相同的话 是不合法的。然后一段攻击方向相同的人的贡献是长度/2,把每一段的贡献都计算出来求和就好了;不过如果所有人的攻击方向都一样的话要特判一下,自己简单模拟一下也很容易发现规律。具体思路见代码。

							代码A
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+15;
typedef long long ll;
ll a[N];
int main()
{
    ll t;
    cin>>t;
    while(t--)
    {
        ll n,f=0;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(int i=2;i<=n;i++)
        {
            if(a[i]!=a[i-1])
                f=1;
        }
        if(f==1)
        {
            cout<<"1"<<endl;
        }
        else
        {
            cout<<n<<endl;
        }
    }
    return 0;
}


						代码B
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+15;
typedef long long ll;
ll a[N];
int main()
{
    ll t;
    cin>>t;
    while(t--)
    {
        ll n,k,maxn,op;
        maxn=-1123456789123;
          op=-1123456789123;
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            maxn=max(maxn,a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=maxn-a[i];
            op=max(op,a[i]);
        }
        if(k%2==1)
        {
            for(int i=1;i<=n;i++)
            {
                cout<<a[i]<<" ";
            }
            cout<<endl; continue;
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=op-a[i];
            //op=max(op,a[i]);
        }
        for(int i=1;i<=n;i++)
        {
             cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}


							代码C
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+15;
typedef long long ll;
int a[N],n;
int dp[N][20];
int mm[N],s[N];
void initRMQ()
{
    mm[0] = -1 ;
    for(int i=1;i<=n;i++)
    {
        mm[i]=  ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
        dp[i][0]=a[i];
    }
    for(int j=1;j<=mm[n];j++)
    {
        for(int i=1;i+(1<<j)-1<=n; i++ )
        {
            dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int rmq(int x,int y)
{
    int k = mm[y-x+1];
    return max(dp[x][k],dp[ y-(1<<k)+1 ][k] );
}
int main()
{
    ll t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(int i=n;i>=2;i--)
        {
            if(a[i]<a[i-1])
                ans+=(a[i-1]-a[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}


					  代码D(DP)
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+15;
typedef long long ll;
char str[N];
ll ans=0;
ll a[N];
ll dp[N][2][2][2][2];
const ll inf=11234567891234;
int main()
{
    ll t,n,k;
    cin>>t;
    while(t--)
    {
        cin>>n; ans=0;
        scanf("%s",str+1);
        for(int i=1;i<=n;i++)
        {
            if(str[i]=='R') a[i]=1;
            else            a[i]=0;
            a[n+i]=a[i];
        }
        int lk=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]==a[n])
                lk=i;
            else
                break;
        }
        for(int i=1;i<=n;i++)
            a[i]=a[lk+i];
        if(n<=2)
        {
            cout<<"0"<<endl;    continue;
        }
        for(int i=2;i<=n;i++)
        {
            if(str[i]!=str[i-1])
            {
                k=i;    break;
            }
        }
        for(int l=1;l<=n;l++)
        {
            for(int i=0;i<=1;i++)
            {
                for(int j=0;j<=1;j++)
                {
                    for(int ii=0;ii<=1;ii++)
                    {
                        for(int jj=0;jj<=1;jj++)
                        {
                            dp[l][i][j][ii][jj]=inf;
                        }
                    }
                }
            }
        }
        if(a[1]==1)
        {
            dp[2][1][0][1][0]=0;
            dp[2][1][1][1][1]=0;
            dp[2][0][0][0][0]=1;
            dp[2][0][1][0][1]=1;
        }
        else
        {
            dp[2][1][0][1][0]=1;
            dp[2][1][1][1][1]=1;
            dp[2][0][0][0][0]=0;
            dp[2][0][1][0][1]=0;
        }
        if(a[2]==1)
        {
            dp[2][1][0][1][0]++;
            //dp[2][1][1][1][1]=0;
            dp[2][0][0][0][0]++;
            //dp[2][0][1][0][1];
        }
        else
        {
            //dp[2][1][0][1][0]++;
            dp[2][1][1][1][1]++;
            //dp[2][0][0][0][0]++;
            dp[2][0][1][0][1]++;
        }
        ll op1,op2,op3;
        for(int l=3;l<=n;l++)
        {
            for(int i=0;i<=1;i++)
            {
                for(int j=0;j<=1;j++)
                {
                    for(int ii=0;ii<=1;ii++)
                    {
                        for(int jj=0;jj<=1;jj++)
                        {
                            op1=op2=op3=inf;
                            if(ii!=0||jj!=0)
                                op1=dp[l-1][i][j][0][ii];
                            if(ii!=1||jj!=1)
                                op2=dp[l-1][i][j][1][ii];
                            if(l==n)
                            {
                                if( ( (ii==jj)&&(jj==i) ) || ((jj==i)&&(i==j)) )
                                    op1=inf,op2=inf;
                            }
                            op3=min(op1,op2);
                            if(a[l]==jj)
                            {
                                dp[l][i][j][ii][jj]=min(dp[l][i][j][ii][jj],op3);
                            }
                            else
                            {
                                dp[l][i][j][ii][jj]=min(dp[l][i][j][ii][jj],op3+1);
                            }
                        }
                    }
                }
            }
        }
        ll opp=inf;
        for(int i=0;i<=1;i++)
        {
            for(int j=0;j<=1;j++)
            {
                for(int ii=0;ii<=1;ii++)
                {
                    for(int jj=0;jj<=1;jj++)
                    {
                        opp=min(opp,dp[n][i][j][ii][jj]);
                    }
                }
            }
        }
        cout<<opp<<endl;
    }
    return 0;
}

						代码D(找规律)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+15;
typedef long long ll;
char str[N];
ll ans=0;
ll a[N];
ll dp[N][2][2][2][2];
const ll inf=11234567891234;
int main()
{
    ll t,n,k;
    cin>>t;
    while(t--)
    {
        cin>>n; ans=0;
        scanf("%s",str+1);
        for(int i=1;i<=n;i++)
        {
            if(str[i]=='R') a[i]=1;
            else            a[i]=0;
            a[n+i]=a[i];
        }
        int lk=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]==a[n])
                lk=i;
            else
                break;
        }
        if(lk==n)
        {
            if(lk<=2)
                cout<<"0"<<endl;
            else
                cout<<(lk+2)/3<<endl;
            continue;
        }
        for(int i=1;i<=n;i++)
            a[i]=a[lk+i];
        ll op=1;
        a[n+1]=3;
        //cout<<a[1]<<" ";
        for(int i=2;i<=n+1;i++)
        {
          //  cout<<a[i]<<" ";
            if(a[i]==a[i-1])
                op++;
            else
            {
                ans+=op/3;  //if(op%3==2&&op>3) ans++;
                op=1;
            }
        }
        //cout<<endl;
        cout<<ans<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值