题意:
这个题好像期末考试那些程序阅读题,其实大家看看程序跑一遍其实就知道每一分段有什么用了。
- 程序一:把最大值放后面。
- 程序二:把最小值放前面。
- 程序三:检测一下该顺序是否排好顺序。
其实这个和逆序数扯上一点关系。
有两种做法:
- 模拟这个过程
- 用树状数组求出最大的逆序数。
模拟:
这个做法似乎很玄乎,但的确是这样做的,不懂的可以在评论区大胆提出来。
做法:首先把开一个结构体 (大小,和输入时的下标),把下标存起来,后来将大小进行排序。
要知道 这一个排序不是两两相邻交换,而是一种直接放到对应位置的,但是过程中把某些数字一同带走。
1 5 2 4 6 3
例如上面的序列,排序把6放到最后的同时,也把5放到前一个位置。
1 2 4 5 3 6
下一个时刻把最小值返回去的同时,把5归位了。
1 2 3 4 5 6
具体代码:
#include<bits/stdc++.h>
using namespace std;
typedef struct node{
int x,No;
}node;
node a[100055];
int cmp(node a,node b){
if(a.x==b.x){
return a.No<b.No;
}
return a.x<b.x;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i].x);
a[i].No=i;
}
sort(a,a+n,cmp);
int temp=0,maxz=1;
int vis[100055]={0};
for(int i=0;i<n;i++){
if(i<a[i].No){
temp++;
}
if(vis[i]){
temp--;
}
vis[a[i].No]=1;
maxz=max(maxz,temp);
}
printf("%d\n",maxz);
return 0;
}
树状数组维护:
其实排序后,你会发现,逆序数对于每一个数来说意义是,在这个数组里面还有多少个没有排好序。
然后去最大值,因为排序还会顺带一些数字排序好。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef struct node {
int No,x;
}node;
node a[N];
int cmp(node a,node b){
if(a.x==b.x) return a.No<b.No;
return a.x<b.x;
}
int n;
int c[N],aa[N];
int lowbit(int x){
return x&(-x);
}
int getsum(int x){
int ret=0;
for(;x>0;x-=lowbit(x)){
ret+=c[x];
}
return ret;
}
int update(int x,int val=1){
for( ;x<=n;x+=lowbit(x)){
c[x]+=val;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].x);
a[i].No=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
aa[a[i].No]=i;
}
int ans=1;
for(int i=1;i<=n;i++){
update(a[i].No);
ans=max(ans,i-getsum(i));
}
printf("%d\n",ans);
return 0;
}