题目:逆序对
参考:
dalao的题解 <-这位大佬写的好清晰的orz
思路:归并的题,但是可以用权值线段树做。
注意:权值线段树就是以权值为下标的线段树,由于权值可能很大,所以要先离散化。
代码:
#include <bits/stdc++.h>
using namespace std;
#define maxn 40000
struct Pair {
int x, y;
Pair(int xx=-1,int yy=-1) {
x=xx,y=yy;
}
bool operator < (const Pair& oth) const {
return y<oth.y||(y==oth.y&&x<oth.x);
}
};
int n,m=0;
Pair a[maxn+5];
int c[maxn+5];
int tr[maxn*4+5]={0};
int p,q=m+1;
void update(int o,int l,int r) {
if(l>p||r<p) return ;
if(l==r) {
tr[o]++;
return ;
}
int lc=o*2,rc=o*2+1,mid=l+(r-l)/2;
update(lc,l,mid),update(rc,mid+1,r);
tr[o]=tr[lc]+tr[rc];
}
int query (int o,int l,int r) {
if(l>m+1||r<p) return 0;
if(l>=p&&r<=m+1) {
return tr[o];
}
int lc=o*2,rc=o*2+1,mid=l+(r-l)/2;
return query(lc,l,mid)+query(rc,mid+1,r);
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i].y);
a[i].x=i;
}
sort(a+1,a+n+1);
for(int i=1; i<=n; i++) {
if(a[i].y!=a[i-1].y) m++;
c[a[i].x]=m;
}
int ans=0;
for(int i=1;i<=n;i++){
p=c[i];
int s=query(1,1,m+1);
ans+=s;
update(1,1,m+1);
}
printf("%d",ans);
return 0;
}
本文介绍了一种使用权值线段树解决逆序对问题的方法。通过对输入数据进行排序和离散化处理,利用线段树进行区间查询与更新操作,有效地计算出数组中逆序对的数量。
705

被折叠的 条评论
为什么被折叠?



