Out of Sorts II(树状数组)

传送门

题意:

这个题好像期末考试那些程序阅读题,其实大家看看程序跑一遍其实就知道每一分段有什么用了。

  1. 程序一:把最大值放后面。
  2. 程序二:把最小值放前面。
  3. 程序三:检测一下该顺序是否排好顺序。

其实这个和逆序数扯上一点关系。

有两种做法:

  1. 模拟这个过程
  2. 用树状数组求出最大的逆序数。

模拟:

这个做法似乎很玄乎,但的确是这样做的,不懂的可以在评论区大胆提出来。

做法:首先把开一个结构体 (大小,和输入时的下标),把下标存起来,后来将大小进行排序。

要知道  这一个排序不是两两相邻交换,而是一种直接放到对应位置的,但是过程中把某些数字一同带走。

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;
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/81258175