bzoj3295[Cqoi2011]动态逆序对
cdq模板
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=100007;
typedef long long LL;
using namespace std;
int n,m,a[N],b[N],pos[N],tot,ans[N],sum[N];
LL now,res[N];
template<typename T>void read(T &x) {
char ch=getchar(); T f=1; x=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
struct node {
int ti,x,y;
node(){}
node(int ti,int x,int y):ti(ti),x(x),y(y){}
friend bool operator <(const node &A,const node &B) {
return A.x<B.x;
}
}p[N],tp[N];
void add(int x,int y) {
for(int i=x;i<=n;i+=(i&(-i)))
sum[i]+=y;
}
int qry(int x) {
int res=0;
for(int i=x;i;i-=(i&(-i)))
res+=sum[i];
return res;
}
void cdq(int l,int r) {
if(r<=l) return;
int mid=((l+r)>>1),ql=l-1,qr=mid;
for(int i=l;i<=r;i++) {
if(p[i].ti<=mid) {
tp[++ql]=p[i];
add(n-p[i].y+1,1);
}
else {
tp[++qr]=p[i];
ans[p[i].ti]+=qry(n-p[i].y+1);
}
}
for(int i=l;i<=ql;i++)
add(n-tp[i].y+1,-1);
for(int i=l;i<=r;i++) p[i]=tp[i];
cdq(l,mid); cdq(mid+1,r);
}
int main() {
#ifdef orzllj
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
read(n); read(m);
for(int i=1;i<=n;i++) {
read(a[i]);
pos[a[i]]=i;
}
for(int i=1;i<=m;i++) {
read(b[i]);
a[pos[b[i]]]=0;
}
for(int i=1;i<=n;i++)
if(a[i]) p[++tot]=node(tot,i,a[i]);
for(int i=m;i>=1;i--)
p[++tot]=node(tot,pos[b[i]],b[i]);
sort(p+1,p+tot+1);
cdq(1,n);
for(int i=1;i<=tot;i++) p[i].x=n-p[i].x+1,p[i].y=n-p[i].y+1;
sort(p+1,p+tot+1);
cdq(1,n);
int cc=m;
for(int i=1;i<=n;i++) {
now+=ans[i];
if(i>n-m) res[cc--]=now;
}
for(int i=1;i<=m;i++) {
printf("%lld\n",res[i]);
}
return 0;
}
/*
5 4
1 5 3 4 2
5 1 4 2
*/