CF 1173C——Nauuo and Cards——(很棒的思维题)

题目链接:https://codeforces.com/contest/1173/problem/C

题意:给你2*n张牌,其中有n个0,n个1<=ai<=n的不重复的数,你手上有n张,队列中有n张,你每次可以选择手上的一张牌放到队列尾部,并从队列首部取出一张牌。问你最少经过多少操作之后,队列中的牌将变得有序?(即1,2,3.....n的排列)

题解:这是一定可以办得到的,因为你可以先把所有的数字数取在手里,再一张张按顺序插入。如果这样做,那我们的答案就是需要取出并插入的最大次数的那张牌,如果用p[i]表示牌i在堆中的位置,牌i只有当它位于i-1处时,它才可以再经过n步走到i处,所以一张牌需要的位移数为p[i]-i+n+1,取最大就好了。

很可惜这样还漏了一种情况:有些牌,它并不需要取出来就可以满足条件。那么,这是种什么情况呢?

只有当牌中有..........1,2,3.....k,这样的排列时,且剩余的k+1,k+2....n均在手上才会出现(注意k是最后一张牌,即位置为n)

这样,1,2,3...k就不必取出了,答案就是n-i。

特判第二种情况就好。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn=2e5+10;
int a[maxn],b[maxn];
int p[maxn];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    memset(p,0,sizeof(p));
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
        p[b[i]]=i;//在堆中各个牌的位置
    }
    //分两种情况

    if(p[1]){//1.在堆中,判断是否有可能出现.....1,2,3...k(后面是有序的)这样的情况
        for(int i=1;p[i]==p[1]+i-1;i++){
            if(p[i]==n){//存在
                //判断k+1,k+2.....n是否都在手上
                int k=i+1;
                for(;k<=n&&p[k]<=k-i-1;k++);
                if(k>n){
                    printf("%d\n",n-i);
                    return 0;
                }
            }
        }

    }
    //2.不在堆中,假设第i张牌再第二个数组中的位置是pi,可以得到只有当其处在i-1这个位置时。才能一下n步出完
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=max(ans,p[i]-i+1+n);
    }
    printf("%d\n",ans);
    return 0;
}

 

你可能感兴趣的:(思维题)