#include<bits/stdc++.h>
using namespace std;
struct node{int val,pos;}a[10];
int n,b[10],sum[103];
bool cmp(node a,node b){
return a.val<b.val;
}
void update(int pos,int v){
while(pos<=n){
sum[pos]+=v;
pos+=pos&(-pos);
}
}
int query(int pos)
{
int rec=0;
while(pos>0){
rec+=sum[pos];
pos-=pos&(-pos);
}
return rec;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].val;
a[i].pos=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
b[a[i].pos]=i;
int ans=0;
for(int i=1;i<=n;i++){
update(b[i],1);
ans+=b[i]-query(b[i]);
}
cout<<ans<<endl;
return 0;
}
离散化+树状数组
作用:
离散化:不改变数据相对大小,进行缩小
树状数组:在logn复杂度下单点更新及查找
题目:
求n个数排列的逆序数(1e5)
样例:
Input output
5 10
99 88 77 66 55
解释:
离散化:用结构体存序列的值(a)及地址(b),按值排序(c)后依次给值对应的地址赋值(d)
树状数组:
关键:pos&(-pos)得到的是pos最低位的1
以10为例,二进制1010,10&(-10)是0010
建树:
当pos<=n说明树中有这个点,sum累加,然后继续更新其父亲pos+(pos&(-pos))
询问:
当pos>0说明还未加完,累加完后更新pos为pos-(pos&(-pos)),依次去掉最低位的1,各对应元素值总和即为所求1-原pos前缀和
逆序数:
以4 5 1 3 2为例,标志数组初始化0 0 0 0 0
第4位填入0 0 0 1 0,1-4位有1个1,+3
第5位填入0 0 0 1 1,1-5位有2个1,+3
第1位填入1 0 0 1 1,1-1位有1个1,+0
第3位填入1 0 1 1 1,1-3位有2个1,+1
第2位填入1 1 1 1 1,1-2位有2个1,+0
逆序数为3+3+1=7
补充:离散化去重(关键会用unique即可)
#include<bits/stdc++.h>
using namespace std;
int main(){
//vector<int>a={1,3,3,4,5,6,6,7};
//vector<int>::iterator cnt=unique(a.begin(),a.end());
//a.erase(cnt,a.end());
int b[8]={1,3,3,4,5,6,6,7};
int nm=unique(b,b+8)-b;
for(int i=0;i<nm;i++)cout<<b[i]<<' ';cout<<endl;
return 0;
}