数据结构学习——动态逆序对

解法一: 分块套BIT

利用树状数组算最初的逆序对个数 nlogn
利用树状数组算出块中比x小的数的个数 logn
遍历x所在的那个块 n/S
总复杂度O( m(lognn/S+S)+nlogn )
S取 nlogn 时 O( mnlogn+nlogn)

#include
#include
#include
using namespace std;
#define M 100005
#define N 80
int A[M],C[M],Cnt[N];
int n,m,S,G;
struct BIT{
    int Sum[M];
    void update(int x,int a){
        while(x<=n)Sum[x]+=a,x+=x&(-x);
    }
    int query(int x){
        int ans=0;
        while(x)ans+=Sum[x],x-=x&(-x);
        return ans;
    }
}Bit[N];

long long Query(int x){
    long long cnt=0;
    int now=(C[x]-1)/S+1;
    for(int i=1;ifor(int i=now+1;i<=G;i++)cnt+=Bit[i].query(x);
    for(int i=(now-1)*S+1;i<=min(n,now*S);i++){
        if(A[i]==0)continue;
        if((A[i]>x&&iC[x]))cnt++;
    }
    return cnt;
}

void Update(int x){
    A[C[x]]=0;
    int now=(C[x]-1)/S+1;
    Cnt[now]--;
    Bit[now].update(x,-1);
}

int main(){
    long long ans=0;
    scanf("%d%d",&n,&m);
    S=sqrt(n*log2(n));
    G=(n-1)/S+1;
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i]),C[A[i]]=i;
        ans+=i-Bit[0].query(A[i])-1;
        Bit[0].update(A[i],1);
    }
    for(int i=1;i<=G;i++)
        for(int j=i*S-S+1;j<=min(i*S,n);j++)
            Bit[i].update(A[j],1),Cnt[i]++;
    for(int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        printf("%lld\n",ans);
        Update(x);
        ans-=Query(x);
    }
    return 0;
}

解法二:BIT套BIT

类似于分块
第一层的BIT就是代替分块的功能
但使用BIT的复杂度会比分块小很多 理解也难了很多
第一层的BIT对应的是下标,第二层的BIT是第一层所管辖到的子树
第二层负责维护信息,第一层负责映射出要查询的东西
可以说要更新一个值,先去找第一层
然后第一层再找第二层
可以说更新的永远是第二层
第一层只负责反馈和指挥第二层

代码实现:

#include
#include
#include
using namespace std;

#define M 100005
#define pb push_back
#define ll long long
int A[M],W[M];
int n,m;

struct NODE{
    int Sum[M];
    void insert(int x){
        while(x<=n){
            Sum[x]++;
            x+=x&-x;
        }
    }
    ll query(int x){
        ll ans=0;
        while(x){
            ans+=Sum[x];
            x-=x&-x;
        }
        return ans;
    }
    ll solve(){
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans+=i-query(A[i])-1;
            insert(A[i]);
        }
        return ans;
    }
}KG;

struct node{
    vector<int>val;
    vector<int>num;
    int sz;
    void init(){
        sort(val.begin(),val.end());
        sz=val.size()-1;
        //erase(unique(val.begin(),vel.end()),val.end());
        for(int i=1;i<=sz;i++){
            num.pb(i&-i);
        }
    }
    void update(int x){
        int k=lower_bound(val.begin(),val.end(),x)-val.begin();//从该点开始更新 
        while(k<(int)val.size()){
            num[k]--;
            k+=k&-k;
        }
        sz--;
    }
    ll query(int x){
        ll ans=0;
        int k=lower_bound(val.begin(),val.end(),x)-val.begin()-1;//从该点前一点查询 
        while(k){
            ans+=num[k];
            k-=k&-k;
        }
        return ans;
    }
}C[M];

ll Getsize(int x){
    ll sum=0;
    while(x){
        sum+=C[x].sz;
        x-=x&-x;
    }
    return sum;
}

ll Getsum(int x,int val){
    ll sum=0;
    while(x){
        sum+=C[x].query(val);
        x-=x&-x;
    }
    return sum;
}

void Init(){
    for(int i=0;i<=n;i++)C[i].val.pb(0),C[i].num.pb(0);
    for(int i=1;i<=n;i++){
        int x=i;
        while(x<=n){
            C[x].val.pb(A[i]);
            x+=x&-x;
        }
    }
}

void Del(int x,int val){
    while(x<=n){
        C[x].update(val);
        x+=x&-x;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i]);
        W[A[i]]=i;
    }
    Init();
    for(int i=1;i<=n;i++)C[i].init();
    long long tmp=KG.solve();
    for(int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        printf("%lld\n",tmp);
        ll sum1=Getsum(W[x]-1,x);
        ll sum2=Getsize(W[x]-1);
        ll sum3=Getsum(n,x);
        tmp-=(sum2-sum1*2+sum3);
        Del(W[x],x);
    }
    return 0;
} 

你可能感兴趣的:(数据结构,——BIT)