先看一道基础题 HRBUST 2224 

给定 n 个数组成的数组,求其逆序对的总数。

逆序对定义为,存在 (i, j) 满足 i < j 且 A[i] > A[j] 的二元组的数目。

接下来的一行,包含 n 个数(2 <= n <= 100000),依次表示 A[i](A[i] <= 10^9)。

简单的逆序对问题,很显然可以用树状数组或者归并排序解决,但是考虑到A的范围,常规的树状数组会采用离散化,tree存储前面比她小的数来解决。

这当然是没有问题的,但是这个题事实上是两个维度(pos,t),pos是一个显而易见的,t其实也是一个维度,也就是出现的顺序,逆序对事实上是要满足(pos1 < pos2 && t1 > t2)的对数,将问题转化为这样的二维来看,pos和t的地位就等同了,我们既然可以用树状数组求pos的前缀来计算逆序数对,当然也可以用t的前缀来计算逆序数对,在常规做法中,t从前向后遍历的时候是保证有序的,所以直接操作即可,当我们用树状数组来维护t的时候,我们就要事先对pos进行排序,此时所有比t小的数都是正常的,我们只要用t减去这些正常的就是这个数的逆序数对。

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
const int MAXBUF=10000;char buf[MAXBUF],*ps=buf,*pe=buf+1;
inline bool isdigit(const char& n) {return (n>='0'&&n<='9');}
inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
template <class T> inline bool in(T &ans){
#ifdef VSCode
ans=0;T f=1;register char c;
do{c=getchar();if ('-'==c)f=-1;}while(!isdigit(c)&&c!=EOF);
if(c==EOF)return false;do{ans=(ans<<1)+(ans<<3)+c-48;
c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
#endif
#ifndef VSCode 
ans =0;T f=1;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-1;} 
while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<1)+(ans<<3)+*ps-48;
rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
#endif
}const int MAXOUT=10000;   //*(int(*)[10])p
char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
template <class T>inline void out_int(T x) {if(!x){out_char('0');return;}
if(x<0)x=-x,out_char('-');int len=0;while(x){outtmp[len++]=x%10+48;x/=10;}outtmp[len]=0;
for(int i=0,j=len-1;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
template<typename T, typename... T2>
inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
#define Vec Point
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,tmp,K; 
PLL a[maxn];
LL tree[maxn];
int lowbit(int t){
    return t & -t;
}
void add(int x){
    while(x <= N){
        tree[x]++;
        x += lowbit(x);
    }
}
LL query(int x){
    LL s = 0;
    while(x > 0){
        s += tree[x];
        x -= lowbit(x);
    }
    return s;
}
int main()
{
    in(N);
    For(i,1,N) in(a[i].fi) ,a[i].se = i;
    sort(a + 1,a + 1 + N);
    LL ans = 0;
    For(i,1,N){
        ans += a[i].se - 1 - query(a[i].se);
        add(a[i].se);
    }
    Prl(ans);
    #ifdef VSCode
    write();
    system("pause");
    #endif
    return 0;
}
View Code

相关文章:

  • 2021-08-12
  • 2021-10-02
  • 2022-12-23
  • 2018-08-27
  • 2021-08-17
  • 2021-12-02
  • 2019-10-11
猜你喜欢
  • 2021-06-06
  • 2022-02-02
  • 2021-07-31
  • 2022-03-02
  • 2021-07-09
  • 2021-10-24
相关资源
相似解决方案