洛谷 P3157 [CQOI2011]动态逆序对
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
可以值域分块,块套树状数组,树套树
不过用序列分块\(+vector\)一样能水过这道题
考虑删去一个点\(x\)对答案产生的影响,拿下面的数列来说
\[1,2……x……n-1,n
\]
对于区间\([1,x-1]\),\(a_i>a_x\)会产生逆序对
对于区间\([x+1,n]\),\(a_i<a_x\)会产生逆序对
那么每次删点后统计一下\(x\)两侧满足条件的数就好了
我们对序列分块,同一个块里的用\(vector\)排好序,和\(x\)在不同块的二分查找更新答案,和\(x\)在同一个块的暴力枚举更新答案,每次删点的时候在\(vector\)里删除点就好了
复杂度大约是\(O(Mlog(N)\sqrt{N})\),吸吸氧就过了
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define N 100000
#define rep(i,s,t) for (register int i=s;i<=t;i++)
#define drep(i,s,t) for (register int i=t;i>=s;i--)
#define il inline
using namespace std;
int n,m,a[N+5],data[N+5],bs,blo[N+5],L[N+5],R[N+5],na[N+5],d[N+5],id[N+5],cnt;
long long ans;
vector <int> p[N+5];
void merge_sort(int l,int r)
{
if (r-l>0)
{
int it=l,mid=l+r>>1,p=l,q=mid+1;
merge_sort(l,mid);
merge_sort(mid+1,r);
while (p<=mid||q<=r)
{
if (q>r||p<=mid&&data[p]<=data[q])
na[it++]=data[p++];
else
{
na[it++]=data[q++];
ans+=(long long)mid-p+1;
}
}
rep(i,l,r)
data[i]=na[i];
}
}
il void del(int x)
{
d[x]=1;
vector <int>::iterator it=lower_bound(p[blo[x]].begin(),p[blo[x]].end(),a[x]);
p[blo[x]].erase(it);
}
il void calc(int x)
{
rep(i,1,blo[x]-1)
ans-=(long long)(p[i].end()-upper_bound(p[i].begin(),p[i].end(),a[x]));
rep(i,L[blo[x]],x-1)
if (a[i]>a[x]&&!d[i])
ans--;
rep(i,x+1,R[blo[x]])
if (a[i]<a[x]&&!d[i])
ans--;
rep(i,blo[x]+1,blo[n])
ans-=(long long)(lower_bound(p[i].begin(),p[i].end(),a[x])-p[i].begin());
}
il int read()
{
int X(0),w(0);char ch(0);
while (!isdigit(ch))w|=ch=='-',ch=getchar();
while (isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
int main()
{
n=read();
m=read();
bs=sqrt(n);
rep(i,1,n)
{
a[i]=read();
data[i]=a[i];
id[a[i]]=++cnt;
blo[i]=(i-1)/bs+1;
if (!L[blo[i]])
L[blo[i]]=i;
R[blo[i]]=i;
p[blo[i]].push_back(a[i]);
}
merge_sort(1,n);
rep(i,1,blo[n])
sort(p[i].begin(),p[i].end());
int x;
rep(i,1,m)
{
printf("%lld\n",ans);
x=read();
del(id[x]);
calc(id[x]);
}
return 0;
}