差分、前缀和

注意到一个数至多被排序一次,如果 $a_i \neq i$ 那么 $a_i$ 就需要被排序,令 $p_i$ 表示 $i$ 在数组 $a$ 中的位置,也就是说至少要对端点为 $i,p_i$ 的区间进行排序。

枚举 $i$ 得到所有需要排序的区间,对所有区间取并得到最终需要排序的区间。时间复杂度 $O(n)$。

#include<bits/stdc++.h>
using namespace std;
int n,ans,a[1000005],p[1000005],sum[1000005];
void solution(){
    cin>>n,ans=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum[i]=0,p[a[i]]=i;
    for(int i=1;i<=n;i++) if(a[i]!=i) ++sum[min(i,p[i])],--sum[max(i,p[i])+1];
    for(int i=1;i<=n;i++) sum[i]+=sum[i-1],ans+=(sum[i]!=0);
    cout<<ans<<'\n';
}
int T;
int main(){
    ios::sync_with_stdio(0);
    cin>>T;
    while(T--) solution();
    return 0;
}
最后修改:2024 年 07 月 17 日
如果觉得我的文章对你有用,请随意赞赏