对于序列A,它的逆序对数定义为满足i
一看到逆序对就要想到树状数组。
维护每个数前面到目前有多少个比自己大。
因为要动态维护,每次只删掉一个数在逆序对中的贡献:及每个数前面有多少个比自己大,每个数后面有多少数比自己小。
先预处理出每个数前面有多少个比自己大ll[i],每个数后面有多少个数比自己小rr[i]。
很显然每次只用总答案删掉位置为i的数,答案就减去ll[i]+rr[i]就可以了,但是有一个问题。
如果已经删掉了一些数在统计进答案里面会重复删减。
那么我们再把已经删减的数用一个数据结构来维护,因为要维护每个数前面与后面的答案,考虑前缀和的思路,自然就是树状数组了,然后在范围内查询个数,用权值线段树就可以了。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long lll;
const int maxn=100007;
int i,j,l,n,m,ll[maxn],rr[maxn],a[maxn],b[maxn];
int tree[maxn],root[maxn],num;
int A[maxn],B[maxn];
lll ans,k;
struct node{
int l,r,sum;
}t[maxn*50];
int lowbit(int x){
return (-x)&x;
}
int get(int x){
int i,j=0;
for(i=x;i;i-=lowbit(i))j+=tree[i];
return j;
}
void add(int x){
int i;
for(i=x;i<=n;i+=lowbit(i))tree[i]++;
}
void build(int &x,int l,int r,int y){
if(!x)x=++num;
t[x].sum++;
if(l==r)return;
int mid=(l+r)/2;
if(y<=mid)build(t[x].l,l,mid,y);
else build(t[x].r,mid+1,r,y);
}
int zhaoda(int x,int y,int z){
A[0]=B[0]=0;x--;
int i,l=1,r=n,mid,k=0;
for(i=x;i;i-=lowbit(i))A[++A[0]]=root[i];
for(i=y;i;i-=lowbit(i))B[++B[0]]=root[i];
while(l2;
if(mid>=z){
fo(i,1,A[0])k-=t[t[A[i]].r].sum;
fo(i,1,B[0])k+=t[t[B[i]].r].sum;
fo(i,1,A[0])A[i]=t[A[i]].l;
fo(i,1,B[0])B[i]=t[B[i]].l;
r=mid;
}
else{
fo(i,1,A[0])A[i]=t[A[i]].r;
fo(i,1,B[0])B[i]=t[B[i]].r;
l=mid+1;
}
}
return k;
}
int zhaoxiao(int x,int y,int z){
A[0]=B[0]=0;x--;
int i,l=1,r=n,mid,k=0;
for(i=x;i;i-=lowbit(i))A[++A[0]]=root[i];
for(i=y;i;i-=lowbit(i))B[++B[0]]=root[i];
while(l2;
if(mid1,A[0])k-=t[t[A[i]].l].sum;
fo(i,1,B[0])k+=t[t[B[i]].l].sum;
fo(i,1,A[0])A[i]=t[A[i]].r;
fo(i,1,B[0])B[i]=t[B[i]].r;
l=mid+1;
}
else{
fo(i,1,A[0])A[i]=t[A[i]].l;
fo(i,1,B[0])B[i]=t[B[i]].l;
r=mid;
}
}
return k;
}
int main(){
// freopen("fan.in","r",stdin);
// freopen("fan.out","w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,n){
scanf("%lld",&a[i]);
b[a[i]]=i;
ll[i]=get(n)-get(a[i]);
ans+=ll[i];
add(a[i]);
}
memset(tree,0,sizeof(tree));
fod(i,n,1){
rr[i]=get(a[i]-1);
add(a[i]);
}
fo(i,1,m){
printf("%lld\n",ans);
scanf("%lld",&k);
ans-=(ll[b[k]]+rr[b[k]]-zhaoda(1,b[k]-1,k)-zhaoxiao(b[k]+1,n,k));
for(j=b[k];j<=n;j+=lowbit(j))build(root[j],1,n,k);
}
}