C84 树状数组套权值线段树 P3157 [CQOI2011] 动态逆序对

视频链接:C84 树状数组套权值线段树 P3157 [CQOI2011] 动态逆序对_哔哩哔哩_bilibili

 

 

 

 

Luogu P3157 [CQOI2011] 动态逆序对

// 树状数组套权值线段树 O(nlognlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define mid ((l+r)>>1)
#define ls (tr[u].l)
#define rs (tr[u].r)
#define lowb(x) (x&-x)
const int N=100005;
int n,m,a[N],pos[N];
int tot,rt[N]; //线段树的根
struct node{
    int s,l,r;
}tr[N*300];    //权值线段
long long ans;

void change(int &u,int l,int r,int v,int k){ //内修
  if(!u) u=++tot;
  tr[u].s+=k;
  if(l==r) return;
  if(v<=mid) change(ls,l,mid,v,k);
  else change(rs,mid+1,r,v,k);
}
void change(int x,int v,int k){ //外修
  while(x<=n) change(rt[x],1,n,v,k), x+=lowb(x);
}
int qmore(int u,int l,int r,int v){ //内查>v的个数
  if(!u) return 0;
  if(v<l) return tr[u].s; //返回>v的个数
  int ret=0;
  ret+=qmore(rs,mid+1,r,v);
  if(v<=mid) ret+=qmore(ls,l,mid,v);
  return ret;
}
int qmore(int x,int v){ //外查>v的个数
  int ret=0;
  while(x) ret+=qmore(rt[x],1,n,v), x-=lowb(x);
  return ret;
}
int qless(int u,int l,int r,int v){ //内查<v的个数
  if(!u) return 0;
  if(v>r) return tr[u].s; //返回<v的个数
  int ret=0;
  ret+=qless(ls,l,mid,v);
  if(v>mid)    ret+=qless(rs,mid+1,r,v);
  return ret;
}
int qless(int x,int v){ //外查<v的个数
  int ret=0;
  while(x) ret+=qless(rt[x],1,n,v), x-=lowb(x);
  return ret;
}
int main(){
  scanf("%d%d",&n,&m); int v;
  for(int i=1;i<=n;i++){
    scanf("%d",&a[i]); pos[a[i]]=i;
    ans+=qmore(i-1,a[i]); //前面>ai的个数
    change(i,a[i],1);
  }
  while(m--){
    printf("%lld\n",ans);
    scanf("%d",&v);
    //减去前面>v的个数,减去总共<v的个数,补回来前面<v的个数
    ans-=qmore(pos[v]-1,v)+qless(n,v)-qless(pos[v]-1,v);
    change(pos[v],v,-1);
  }
}

 

posted @ 2023-12-31 13:30  董晓  阅读(217)  评论(0编辑  收藏  举报