传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=3295
题目大意
给定1~n的序列,每次删去一个数,询问每次删之前的逆序对数
题解
我们把它转化成CDQ模型
删除,我们可以倒过来看成添加
对于每个数我们给他一个时间戳,本身的权值和它在序列中的位置
这样就转化成了一个三维点对间的问题
我们再看逆序对
每个点时间戳在它后面的分为两种情况
1.序列中位置在它后面,权值比它小
2.序列中位置在它前面,权值比它大
分开处理即可
注意ans要用longlong
const
maxn=100005;
type
data=record
x,y,z:longint;
end;
var
pp,temp,ask:array[0..maxn]of data;
tt,bit,que:array[0..maxn]of longint;
ans:array[0..maxn]of int64;
i,j,k:longint;
n,m,len,kind:longint;
procedure sort(l,r:longint);
var i,j,a,b,c:longint; d:data;
begin
i:=l; j:=r; a:=ask[(l+r)div 2].x; b:=ask[(l+r)div 2].y; c:=ask[(l+r)div 2].z;
repeat
while (ask[i].x<a)or((ask[i].x=a)and(ask[i].y<b)and(kind=1))or((ask[i].x=a)and(ask[i].z<c)and(kind=2)) do inc(i);
while (ask[j].x>a)or((ask[j].x=a)and(ask[j].y>b)and(kind=1))or((ask[j].x=a)and(ask[j].z>c)and(kind=2)) do dec(j);
if not(i>j) then
begin
d:=ask[i]; ask[i]:=ask[j]; ask[j]:=d;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
procedure update(pos,val:longint);
begin
while pos<=n do
begin
inc(bit[pos],val);
inc(pos,pos and (-pos));
end;
end;
function query(pos:longint):longint;
var sum:longint;
begin
sum:=0;
while pos>0 do
begin
inc(sum,bit[pos]);
dec(pos,pos and (-pos));
end;
exit(sum);
end;
procedure cdq1(l,r:longint);
var mid,i,j,k:longint;
begin
if l=r then exit;
mid:=(l+r)>>1;
cdq1(l,mid); cdq1(mid+1,r);
i:=l; j:=mid+1; len:=l-1;
while (i<=mid)and(j<=r) do
if ask[i].y<ask[j].y
then begin inc(len); temp[len]:=ask[i]; update(ask[i].z,1); inc(i); end
else begin inc(len); temp[len]:=ask[j]; inc(ans[ask[j].x],query(n)-query(ask[j].z)); inc(j); end;
while i<=mid do
begin inc(len); temp[len]:=ask[i]; update(ask[i].z,1); inc(i); end;
while j<=r do
begin inc(len); temp[len]:=ask[j]; inc(ans[ask[j].x],query(n)-query(ask[j].z)); inc(j); end;
for i:=l to mid do
update(ask[i].z,-1);
for i:=l to r do
ask[i]:=temp[i];
end;
procedure cdq2(l,r:longint);
var mid,i,j,k:longint;
begin
if l=r then exit;
mid:=(l+r)>>1;
cdq2(l,mid); cdq2(mid+1,r);
i:=l; j:=mid+1; len:=l-1;
while (i<=mid)and(j<=r) do
if ask[i].z<ask[j].z
then begin inc(len); temp[len]:=ask[i]; update(ask[i].y,1); inc(i); end
else begin inc(len); temp[len]:=ask[j]; inc(ans[ask[j].x],query(n)-query(ask[j].y)); inc(j); end;
while i<=mid do
begin inc(len); temp[len]:=ask[i]; update(ask[i].y,1); inc(i); end;
while j<=r do
begin inc(len); temp[len]:=ask[j]; inc(ans[ask[j].x],query(n)-query(ask[j].y)); inc(j); end;
for i:=l to mid do
update(ask[i].y,-1);
for i:=l to r do
ask[i]:=temp[i];
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(que[i]);
tt[que[i]]:=i;
end;
len:=0;
for i:=m+1 downto 2 do
begin
inc(len);
readln(ask[len].z);
ask[len].x:=i;
ask[len].y:=tt[ask[len].z];
que[ask[len].y]:=-1;
end;
for i:=1 to n do
begin
if que[i]=-1 then continue;
inc(len);
ask[len].x:=1;
ask[len].y:=i;
ask[len].z:=que[i];
end;
fillchar(bit,sizeof(bit),0);
fillchar(ans,sizeof(ans),0);
kind:=1; sort(1,n);
for i:=1 to n do
pp[i]:=ask[i];
cdq1(1,n);
for i:=1 to n do ask[i]:=pp[i];
cdq2(1,n);
for i:=2 to m+1 do
ans[i]:=ans[i-1]+ans[i];
for i:=m+1 downto 2 do
writeln(ans[i]);
end.