动态逆序对[CQOI2011]
此题正解 树套树
&&CDQ也要会啦
首先按删除顺序,给每个点赋时间值,没删的赋inf
按时间从小到大排序,后删除的对先删除的莫得贡献,但是先删除的对后删除的有贡献
第二维 按pos值从小到大排序
维护两个东西
{posi>posj&&vali<valj}
然后 莫得了
#include<bits/stdc++.h>
#define re return
#define lowbit(x) (x&(-x))
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
const int maxn=100005;
using namespace std;
template<typename T>inline void rd(T& x)
{
char c;bool f=0;
while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
x=c^48;
while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
if(f)x=-x;
}
int n,m,c[maxn],pos[maxn],d[maxn];
long long ans;
struct node{
int timme,val,pos,ans;
bool operator<(node a)const
{re timme<a.timme;}
}num[maxn],t[maxn];
inline void add(int x,int y){while(x<=n){c[x]+=y;x+=lowbit(x);}}
inline int sum(int x)
{
int res=0;
while(x)
{res+=c[x];x-=lowbit(x);}
re res;
}
inline void CDQ(int l,int r)
{
if(l==r) re;
int mid=(l+r)>>1;
CDQ(l,mid),CDQ(mid+1,r);
int q=r,tot=l;
dec(i,mid,l)
{
while(q>mid&&num[q].pos>num[i].pos)add(num[q].val,1),--q;
num[i].ans+=sum(num[i].val-1);
}
inc(i,q+1,r)add(num[i].val,-1);
q=mid+1;
inc(i,l,mid)
{
while(q<=r&&num[q].pos<num[i].pos)
{
add(num[q].val,1);
t[tot++]=num[q];
++q;
}
num[i].ans+=sum(n)-sum(num[i].val);
t[tot++]=num[i];
}
inc(i,mid+1,q-1)add(num[i].val,-1);
inc(i,l,tot-1)num[i]=t[i];
inc(i,tot,r)num[i]=num[q++];
}
int main()
{
freopen("in.txt","r",stdin);
int x;
rd(n);rd(m);
inc(i,1,n)
{
rd(num[i].val);
num[i].pos=i;
pos[num[i].val]=i;
num[i].timme=n;
}
inc(i,1,m)
{
rd(d[i]);
num[pos[d[i]]].timme=i;
}
sort(num+1,num+n+1);
CDQ(1,n);
inc(i,1,n)ans+=num[i].ans;
inc(i,1,m)
{
printf("%d\n",ans);
ans-=num[pos[d[i]]].ans;
}
re 0;
}