2018.07.10 NOIP模拟 sort

Sort
题目背景
SOURCE:NOIP2016-RZZ-4 T1
题目描述
给你一个长度为 n 的排列,小W每次可以选择一个数,做以下操作:
不断把这个数与它右边的数交换。
当它右边没有数,或它右边的数比它大时,停止操作。
比如序列 1 4 3 2 5,对 4 操作后就是 1 3 2 4 5 。
求最少需要进行几次操作,使得这个排列变成升序。
输入格式
第一行一个正整数 n 。
第二行 n 个数,从左到右描述给定的排列。
输出格式
输出一个数表示答案。
样例数据 1
输入
5
3 2 5 1 4
输出
3
备注
【样例说明】
按顺序选 5,2,3 。
【数据规模与约定】
对于 30% 的数据,n≤100。
对于 50% 的数据,n≤1000。
对于 100% 的数据,n≤1000000。

一眼题。先说一个显然的结论,若有 i < j a n d a i > a j ,就至少需要一次操作来调整 i 到正确的位置。这个道理想通之后这道题就简单了。我们维护一个单调队列保证队列里的元素单调递增,整个数列遍历完之后从队列中弹出的数显然都需要调整,而对于每个弹出的数又都只需要一次操作,因此答案就是弹出的数的数量。

代码如下:

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    return ans;
}
int n,a[N],ans=0,head,tail,q[N];
int main(){
//  freopen("sort.in","r",stdin);
//  freopen("sort.out","w",stdout);
    n=read(),head=1,tail=0;
    for(int i=1;i<=n;++i){
        a[i]=read();
        while(head<=tail&&a[i]<q[tail])++ans,--tail;
        q[++tail]=a[i];
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/80984453
今日推荐