主席树套树状数组。
主席树第一题。
链接
静态的逆序对问题很简单,用线段树或者是树状数组即可解决。
现在的问题是如何解决一道动态的逆序对问题?
我们先把所有的逆序对统计出来。
每次删除数,我们可以把这个数对于逆序对个数的贡献删除出去。
这个贡献如何统计呢?
Front[i]记录i位置之前有多少个数比这个数大
Back[i]记录i位置之后有多少个数比这个数小
每次删除的贡献就是这两个数之和
放屁!
如果之前我们已经删除过了一些数据,不就减少的多了?
如何统计呢?
把删除的数扔入主席树。
而查询前面多少个比这个数大的,和后面多少个数比这个小,主席树的基本功能!
需要注意的是。
本题要开long long。
本题也可以通过CDQ分治以及暴力分块的方法解决。
日后想起来在写!(主要是不会。)
#include <cstdio>
#include <iostream>
#include <cstring>
#define il inline
#define lowbit(x) x&-x
#define ll long long
using namespace std;
const int maxm=1e6+100;
int root[maxm];
int sum[maxm<<5],lson[maxm<<5],rson[maxm<<5];
int front[maxm],back[maxm];
int tree[maxm],pos[maxm],val[maxm];
int A[maxm],B[maxm];
int n,m,size;
il ll ask(int x)
{
ll ret=0;
for(int i=x;i;i-=lowbit(i))
ret+=tree[i];
return ret;
}
il void up(int x)
{
for(int i=x;i<=n;i+=lowbit(i)) tree[i]++;
}
inline void updata(int &o,int l,int r,int valx)
{
if (!o) o=++size;sum[o]++;
if (l==r) return;
int mid=(l+r)>>1;
if (valx<=mid) updata(lson[o],l,mid,valx);
else updata(rson[o],mid+1,r,valx);
}
il ll ask_big(int l,int r,int valx)
{
if(l>r) return 0;
l--,A[0]=B[0]=0;
for(int i=l;i;i-=lowbit(i)) A[++A[0]]=root[i];
for(int i=r;i;i-=lowbit(i)) B[++B[0]]=root[i];
l=1,r=n;
ll ans=0;
while(l!=r)
{
int mid=(l+r)>>1;
if(valx<=mid)
{
for(int i=1;i<=B[0];i++) ans+=(ll)sum[rson[B[i]]];
for(int i=1;i<=A[0];i++) ans-=(ll)sum[rson[A[i]]];
for(int i=1;i<=B[0];i++) B[i]=lson[B[i]];
for(int i=1;i<=A[0];i++) A[i]=lson[A[i]];
r=mid;
}
else
{
for(int i=1;i<=A[0];i++) A[i]=rson[A[i]];
for(int i=1;i<=B[0];i++) B[i]=rson[B[i]];
l=mid+1;
}
}
return ans;
}
il ll ask_less(int l,int r,int valx)
{
if(l>r) return 0;
l--,A[0]=B[0]=0;
for(int i=l;i;i-=lowbit(i)) A[++A[0]]=root[i];
for(int i=r;i;i-=lowbit(i)) B[++B[0]]=root[i];
l=1,r=n;
ll ans=0;
while(l!=r)
{
int mid=(l+r)>>1;
if(valx>mid)
{
for(int i=1;i<=B[0];i++) ans+=(ll)sum[lson[B[i]]];
for(int i=1;i<=A[0];i++) ans-=(ll)sum[lson[A[i]]];
for(int i=1;i<=B[0];i++) B[i]=rson[B[i]];
for(int i=1;i<=A[0];i++) A[i]=rson[A[i]];
l=mid+1;
}
else
{
for(int i=1;i<=A[0];i++) A[i]=lson[A[i]];
for(int i=1;i<=B[0];i++) B[i]=lson[B[i]];
r=mid;
}
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
ll ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
pos[val[i]]=i;
ans+=(ll)(front[i]=i-1-ask(val[i]));
up(val[i]);
}
memset(tree,0,sizeof(tree));
for(int i=n;i>=1;i--)
back[i]=ask(val[i]-1),up(val[i]);
//printf("%d\n",m);
for(int i=1,del;i<=m;i++)
{
printf("%lld\n",ans);
scanf("%d",&del);
//printf("%d %d\n",front[pos[del]],back[pos[del]]);
int poi=pos[del];
ans-=((ll)front[poi]-ask_big(1,poi-1,del)+(ll)back[poi]-ask_less(poi+1,n,del));
for(;poi<=n;poi+=lowbit(poi))
updata(root[poi],1,n,del);
}
//printf("--%d--\n",ans);
return 0;
}