题意:给出一个1,2,...,n的一个排列,然后删除一些数,每次删除之前,输出当前的逆序对数
思路:维护两个值,tree表示当前层,每一个线段树区间的树状数组,维护已经删除了多少个数,order维护,每一个线段树区间排好序的数列
每次输出答案后,进行更新,首先把当前这个数位置之前大于他的减掉,后面小于他的减掉,然后把这个位置标记为删除掉过
/*
*线段树套树状数组
*gaolee
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=200010;
int N,M;
int tree[30][maxn];
int order[30][maxn];
int X[maxn],tmp[maxn];
LL ans;
void add(int *s,int x,int n,int val)
{
while(x<=n)
{
s[x]+=val;
x+=(x&(-x));
}
}
int getsum(int *s,int x,int n)
{
int sum=0;
while(x>n)
{
sum+=s[x];
x-=(x&(-x));
}
return sum;
}
void build(int o,int l,int r,int d)
{
for(int i=l;i<=r;i++)
order[d][i]=order[d-1][i],tree[d][i]=0;
if(l==r)return ;
int mid=(l+r)>>1;
build(o<<1,l,mid,d+1);
build(o<<1|1,mid+1,r,d+1);
sort(order[d]+l,order[d]+r+1);
}
int bitser(int a,int b,int d,int v)
{
int l = a,r = b,md;
while(l < r){
md = (l + r) >> 1;
if(order[d][md]>=v)r = md;
else l = md + 1;
}
if(order[d][l]>v)--l;
return l;
}
void query(int o,int l,int r,int q1,int q2,int x,int d,int flag)
{
if(q1<=l&&r<=q2)
{
int k=lower_bound(order[d]+l,order[d]+r+1,x)-order[d];
if(order[d][k]>x||k>r)k--;
int t=getsum(tree[d],k,l-1);
if(!flag)
{
k=r-k;
t=getsum(tree[d],r,l-1)-t;
}
else k-=l-1;
ans-=k-t;
return ;
}
if(l>=r)return ;
int mid=(l+r)>>1;
if(q1<=mid)query(o<<1,l,mid,q1,q2,x,d+1,flag);
if(q2>mid)query(o<<1|1,mid+1,r,q1,q2,x,d+1,flag);
}
void update(int o,int l,int r,int pos,int x,int d)
{
if(l==r)
{
add(tree[d],l,r,1);
return ;
}
if(l>=r)return ;
int mid=(l+r)>>1;
if(pos<=mid)update(o<<1,l,mid,pos,x,d+1);
else update(o<<1|1,mid+1,r,pos,x,d+1);
int k=lower_bound(order[d]+l,order[d]+r+1,x)-order[d];
add(tree[d],k,r,1);
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
ans=0;
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=N;i++)
{
scanf("%d",&order[0][i]);
X[order[0][i]]=i;
ans+=(i-1-getsum(tmp,order[0][i],0));
add(tmp,order[0][i],N,1);
}
build(1,1,N,1);
while(M--)
{
int x;
scanf("%d",&x);
printf("%lld\n",ans);
if(ans)
{
query(1,1,N,1,X[x]-1,x,1,0);
query(1,1,N,X[x]+1,N,x,1,1);
update(1,1,N,X[x],x,1);
}
}
}
return 0;
}
目前分块做法处于WA阶段,不知道错哪了
/*
*分块
*gaolee
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=200010;
const int maxm=4010;
int N,M;
int A[maxn],pos[maxn],tmp[maxn];
int size;
int block[maxm][maxm];
int st[maxn],vis[maxn];
LL ans;
void add(int *s,int x,int n,int val)
{
while(x<=n)
{
s[x]+=val;
x+=(x&(-x));
}
}
int getsum(int *s,int x,int n)
{
int sum=0;
while(x>n)
{
sum+=s[x];
x-=(x&(-x));
}
return sum;
}
void init()
{
size=int(sqrt(N));
int num=0,j=0;
for(int i=0;i<N;i++)
{
block[num][j]=A[i];
if(++j==size){num++,j=0;}
}
for(int i=0;i<num;i++)sort(block[i],block[i]+size);
if(j)sort(block[num],block[num]+j);
for(int i=0;i<=num;i++)st[i]=i*size;
}
void QueryMax(int l,int r,int x)
{
int xpos=l/size,ypos=r/size;
if(xpos==ypos)
{
for(int i=l;i<=r;i++)
if(!vis[i]&&A[i]>x)ans--;
}
else
{
for(int i=l;i<(xpos+1)*size;i++)
if(!vis[i]&&A[i]>x)ans--;
for(int i=ypos*size;i<=r;i++)
if(!vis[i]&&A[i]>x)ans--;
for(int i=xpos+1;i<ypos;i++)
if(st[i]<(i+1)*size)
ans-=(i+1)*size-(lower_bound(block[i]+st[i],block[i]+size,x)-block[i]);
}
}
void QueryMin(int l,int r,int x)
{
int xpos=l/size,ypos=r/size;
if(xpos==ypos)
{
for(int i=l;i<=r;i++)
if(!vis[i]&&A[i]<x)ans--;
}
else
{
for(int i=l;i<(xpos+1)*size;i++)
if(!vis[i]&&A[i]<x)ans--;
for(int i=ypos*size;i<=r;i++)
if(!vis[i]&&A[i]<x)ans--;
for(int i=xpos+1;i<ypos;i++)
if(st[i]<(i+1)*size)
ans-=lower_bound(block[i]+st[i],block[i]+size,x)-block[i]-st[i];
}
}
void update(int x,int val)
{
int bpos=x/size;
int p=0;
while(p<size&&block[bpos][p]<val)p++;
if(p==size)p--;block[bpos][p]=-1;
while(p>0&&block[bpos][p]<block[bpos][p-1])
{
swap(block[bpos][p],block[bpos][p-1]),p--;
}
st[bpos]++;
}
int main()
{freopen("in.txt","r",stdin);
while(scanf("%d%d",&N,&M)!=EOF)
{
ans=0;
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=N;i++)
{
scanf("%d",&A[i]);
ans+=(i-1-getsum(tmp,A[i],0));
add(tmp,A[i],N,1);
}
for(int i=0;i<N;i++)
{
A[i]=A[i+1];
A[i]--;
pos[A[i]]=i;
}
memset(vis,0,sizeof(vis));
init();
while(M--)
{
int x;
scanf("%d",&x);
x--;
printf("%lld\n",ans);
int X=pos[x]/size;
if(ans)
{
if(X*size-1>0)QueryMax(0,X*size-1,x);
if((X+1)*size<N)QueryMin((X+1)*size,N-1,x);
for(int i=X*size;i<pos[x];i++)
if(!vis[i]&&A[i]>x)ans--;
for(int i=pos[x]+1;i<min((X+1)*size,N);i++)
if(!vis[i]&&A[i]<x)ans--;
update(pos[x],x);
vis[pos[x]]=1;
}
}
}
return 0;
}