F. Shift and Reverse

发布时间 2023-12-08 21:14:55作者: 纯粹的

戳这里,看原题

多重思想的巧妙结合

不多说了,看代码就懂了

#include<bits/stdc++.h>
using namespace std;
int up[200006]={0},down[200006]={0};
int a[200006]={0};
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=n+1;i<=2*n;i++)a[i]=a[i-n];//拆”环“成链,真的太巧妙了,隐含着环的感觉

        up[1]=down[1]=1;
        for(int i=2;i<=2*n;i++)
        {
            up[i]=a[i]>=a[i-1]?up[i-1]+1:1;//代表该点在该点所在的最长非单调递减序列中排第几
            down[i]=a[i]<=a[i-1]?down[i-1]+1:1;//同理,不过是最长非单调递增序列
        }
        int ans=2e9;
        for(int i=n;i<=2*n-1;i++)//如果存在,那么序列的末尾一定大于等于n
        {
            int lr=(2*n-i)%n;//left right,意思是右边剩下的数量。特殊点在于当i==n时为零
            if(up[i]==n)ans=min(ans,min(lr,1+n-lr+1));//对于递增序列,要么把右边的数全部往前移,要么反转一下把包括自己在内的左边的数全部往前移(翻转过来之后就成了右边的数)
            if(down[i]==n)ans=min(ans,min(lr+1,1+n-lr));//同理,这里千万要仔细,最好写的时候嘴里念叨念叨
        }
        printf("%d\n",ans==2e9?-1:ans);
        //for(int i=1;i<=2*n;i++)printf("%d  ",a[i]);//debug
        //puts("");
        //for(int i=1;i<=2*n;i++)printf("%d   %d\n",up[i],down[i]);
    }
    return 0;
}