排序

阅读程序,题目给出的排序算法是稳定的,然而数组中存在相同元素,同时每次修改之后排序的时间不可接受。考虑解决这些问题。

首先对序列进行双关键字排序,值为第一关键字,下标为第二关键字,然后记录原先序列中下标为 $i$ 的元素排序后的下标,这样可以 $O(1)$ 回答每个询问。

对于修改操作有两种处理方法,时间复杂度同为 $O(n)$。

  • 在排序后的序列中找到被修改的元素并修改,然后在序列上向左右各冒泡一轮。
  • 把被修改的元素单独拎出来形成一个序列,其余元素形成一个序列,归并两个序列。

处理完毕后 $O(n)$ 更新答案序列。

记修改操作的次数为 $m$,总体时间复杂度 $O(n \log n + nm + q)$。

#include<bits/stdc++.h>
using namespace std;
pair<int,int> a[8'005];
int n,q,ans[8'005];
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i].first);
        a[i].second=i;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) ans[a[i].second]=i;
    for(int i=1;i<=q;i++){
        static int x,y,opt;
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d%d",&x,&y);
            for(int j=1;j<=n;j++) if(a[j].second==x) a[j].first=y;
            for(int j=1;j<=n-1;j++) if(a[j]>a[j+1]) swap(a[j],a[j+1]);
            for(int j=n-1;j>=1;j--) if(a[j+1]<a[j]) swap(a[j],a[j+1]);
            for(int j=1;j<=n;j++) ans[a[j].second]=j;
        }
        else{
            scanf("%d",&x);
            printf("%d\n",ans[x]);
        }
    }
    return 0;
}
最后修改:2024 年 09 月 08 日
如果觉得我的文章对你有用,请随意赞赏