版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq872425710/article/details/82864898
题目大意:
给定一个长度为 N 的序列,每次操作可以选选择一个数,这个数和它右边的数比大小,如 果这个数比较大,就和右边的数交换,然后和右边的数接着比大小直到某一次它右边的数比 他大或者他右边没有数了。求最小的操作次数使得序列变为升序。
思路:
因为交换是不会改变相对顺序的,所以从左往右找,找到一个数右边有比他大的就要答案加一。
程序:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 1000005
using namespace std;
struct tree{int a;}t[N*8];
int n,ans;
int a[N];
bool find(int rt,int l,int r,int x,int y){
if (l==x&&r==y) return t[rt].a;
int mid=(l+r)/2;
if (mid<x) return find(rt*2+1,mid+1,r,x,y);
else if (mid>=y) return find(rt*2,l,mid,x,y);
else return find(rt*2+1,mid+1,r,mid+1,y)&find(rt*2,l,mid,x,mid);
}
void insert(int rt,int l,int r,int x){
if (l==r){
t[rt].a=1;
return;
}
int mid=(l+r)/2;
if (x<=mid) insert(rt*2,l,mid,x);
else insert(rt*2+1,mid+1,r,x);
t[rt].a=t[rt*2].a&t[rt*2+1].a;
}
int main(){
freopen("snowman.in","r",stdin);
freopen("snowman.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if (a[i]!=1) if (!find(1,1,n,1,a[i]-1)) ans++;
insert(1,1,n,a[i]);
}
printf("%d",ans);
}