离散化+树状数组

#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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值