每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Codeforces Round #852 (Div. 2)(C,D)

Codeforces Round #852 (Div. 2)(C,D)

B

这个题大意是给你一个\(x\),\(y\),\(x\)是极大值(\(a_i>a_{i+1},a_i>a_{i+1}\))的和,

\(y\)是极小值(\(a_i<a_{i+1},a_i<a_{i+1}\))的和

然后还告诉我们每两个相邻的数相差\(1\),\(a_1\)\(a_2\)\(a_n\)

我们要求最短的一个数组满足这个和的条件

案例给出我们这个和是由多个数组成,其实这个也可以由一个数组成,那么我们只需要构造一个最高点\(x\),最低点\(y\),这样也是最短长度,其实我们不太需要考虑这么多,\(cf\)其实很多套路的

然后我直接构造即可

其实这次的\(B\)我还想了好久,看了题目案例,还以为需要考虑很多,想多了

C

C

这个题的大意是给你一个数组,我们有一个要求得到一对\(l\),\(r\),要求在\([l,r]\)这一段的数,其中所有的数的最大值和最小值不在两端,在中间,问有多少对这样的\(l\),\(r\)

我第一印象就是直接求,枚举\(l\)\(1\)开始,\(r\)\(n\)开始,\(l\)向右移动,\(r\)向左移动,如果满足条件就输出答案

#include <iostream>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int t;
int n;
int a[maxn];
void solve()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    if (n<=2)
    {
        cout<<-1<<'\n';
        return ;
    }
    int step=1;
    int l=1,r=n;
    int mi=1,mx=n;
    while (l<r)
    {
        int ll=l,rr=r;
        while (a[l]==mi&&l<r)//只能一个一个移动,可能中间会出现可能的情况
        {
            l++;
            mi++;
        }
        while (a[l]==mx&&l<r)
        {
            l++;
            mx--;
        }
        while (a[r]==mi&&l<r)
        {
            r--;
            mi++;
        }
        while  (a[r]==mx&&l<r)
        {
           r--;
           mx--;
        }
        if (l==ll&&r==rr) break;//这个就是l,r上不是最小值
    }
    if (r-l<=1) cout<<-1<<'\n';//不可以是两个相邻或者是长度为1的
    else cout<<l<<" "<<r<<"\n";
    return ;
}
signed main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

D

D

这个题大意还是求\([l,r]\)这一段的\(p\)\(q\)\(mex\)是一样的的数量

我们只需要列举每一个\(mex\)的值,然后对于每一种\(mex\)\(l\)\(r\)都会有一个范围,然后直接求即可

具体看代码

#include <iostream>
#include <cmath>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int t,p[maxn],q[maxn],invp[maxn],invq[maxn],n;
void solve()
{
    int ans=0;
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>p[i];
        invp[p[i]]=i;
    }
    for (int i=1;i<=n;i++)
    {
        cin>>q[i];
        invq[q[i]]=i;
    }
    int maxl=n+1,minr=0;
    for (int mex=2;mex<=n+1;mex++)
    {
        minr=max(minr,max(invp[mex-1],invq[mex-1]));//r至少也要包括[1,mex-1]的数
        maxl=min(maxl,min(invp[mex-1],invq[mex-1]));//l最大l是最小的那一个mex-1的位置,那么这个l,r的范围里面一定有[1,mex-1](p和q里面)
        int maxr=n,minl=1;
        if (mex<=n)
        {
            if (invp[mex]<maxl)
            {
                minl=max(minl,invp[mex]+1);//在后面一个,不可选mex
            }
            else 
            {
                maxr=min(maxr,invp[mex]-1);//在前面面一个,不可选mex
            }
            if (invq[mex]<maxl)
            {
                minl=max(minl,invq[mex]+1);
            }
            else
            {
                maxr=min(maxr,invq[mex]-1);
            }
        }
        if (minl<=maxl&&minr<=maxr)
        {
            ans+=(maxl-minl+1)*(maxr-minr+1);
        }
    }
    int len=min(invp[1],invq[1])-1;//这个是mex=1的情况
    ans+=len*(len+1)/2;
    len=n-max(invp[1],invq[1]);
    ans+=len*(len+1)/2;
    len=abs(invp[1]-invq[1])-1;
    ans+=len*(len+1)/2;
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    int t=1;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}
posted @ 2023-02-13 15:31  righting  阅读(37)  评论(0)    收藏  举报