资料:
求逆序对:https://blog.csdn.net/ssimple_y/article/details/53744096
离散化:https://blog.csdn.net/xiangaccepted/article/details/73276826
一、离散化+求逆序对数
//a[i] = 5, 将5插进数组,然后求5和5前面出现的数x,本来5是第i个出现,前面出现了x-1个比5小的,所以i-1-(x-1)就是前面出现的比5大的数,就是逆序对数。 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 5e5+10; const double eps = 1e-8; const double pi = acos(-1.0); int a[maxn],t[maxn],c[maxn]; int n; int getsum(int x) { int sum = 0; while(x>0) { sum += c[x]; x -= x&(-x); } return sum; } void add(int x,int k) { while(x<=n) { c[x] += k; x += x&(-x); } } int main() { while(scanf("%d",&n)!=EOF&&n) { for(int i=1;i<=n;i++) { c[i] = 0; scanf("%d",&a[i]); t[i] = a[i]; } sort(t+1,t+n+1); int m = unique(t+1,t+1+n)-t-1; for(int i=1;i<=n;i++) { a[i] = lower_bound(t+1,t+1+m,a[i])-t; } ll ans = 0; for(int i=1;i<=n;i++) { add(a[i],1); ans += (ll)i-getsum(a[i]); //i第i个位置,getsum(a[i])=a[i]前出现的数 //a[i] = 5, 将5插进数组,然后求5和5前面出现的数x,本来5是第i个出现,前面出现了x-1个比5小的,所以i-1-(x-1)就是前面出现的比5大的数,就是逆序对数。 } printf("%lld ",ans); } }
正反求两次逆序对(对于第i项,求前面比i小的和前面比i大的,求后面比i小的和后面比i大的)
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define lowbit(x) x&(-x) #define readint(x) scanf("%d",&x); #define readll(x) scanf("%lld",&x); #define readdb(x) scanf("%lf",&x); #define reads(x) scanf("%s",x); #define rep(i,l,r) for(int i=l;i<=r;++i) #define per(i,r,l) for(int i=r;i>=l;--i) using namespace std; typedef long long ll; const int maxn = 3e5+10; const double eps = 1e-8; const double pi = acos(-1.0); ll a[maxn],c[maxn]; int n; ll getsum(ll x) { ll sum = 0; while(x>0) { sum += c[x]; x -= lowbit(x); } return sum; } void add(ll x,ll k) { while(x<maxn) { c[x] += k; x += lowbit(x); } } ll nxt_big[maxn],nxt_small[maxn],pre_big[maxn],pre_small[maxn]; int main() { int T; readint(T); while(T--) { int n; readint(n); int x,y; memset(pre_small,0,sizeof(pre_small)); memset(pre_big,0,sizeof(pre_big)); memset(nxt_small,0,sizeof(nxt_small)); memset(nxt_big,0,sizeof(nxt_big)); memset(c,0,sizeof(c)); memset(a,0,sizeof(a)); rep(i,1,n) { readll(a[i]); pre_small[i] = getsum(a[i]); add(a[i],1); pre_big[i] = i-pre_small[i]-1; } memset(c,0,sizeof(c)); per(i,n,1) { nxt_small[i] = getsum(a[i]); add(a[i],1); nxt_big[i] = n-i-nxt_small[i]; } ll ans = 0; rep(i,1,n) { ans += pre_small[i]*nxt_big[i]; ans += pre_big[i]*nxt_small[i]; } printf("%lld ",ans); } }