bzoj 2141 线段树套平衡树
用树套树来解决这个问题,存储每个节点的数值是多少,然后交换
对于答案的变更可以讨论下,假设交换的是x,y位置的数x<=y
如果x=y || high[x]=high[y]则对答案没有影响
如果high[x]<high[y],那么首先交换x,y会对这两个点的逆序对数增加1,否则减小1
那么这是对于这两个数中间的数的逆序对的影响就是:
x的移动会令在这个区间里比x权值小的数与x不在为逆序对,所以答案减少个数
同时令比x的权值大的数多一个与x的逆序对,所以答案增加个数。
y类似,在此不再赘述
/************************************************************** Problem: 2141 User: BLADEVIL Language: Pascal Result: Accepted Time:3408 ms Memory:79600 kb ****************************************************************/ //By BLADEVIL type rec =record left, right, root :longint; end; var n, m :longint; high :array[0..20010] of longint; t :array[0..100040] of rec; b_left, b_right, b_key :array[0..5000010] of longint; b_size :array[0..5000010] of longint; tot :longint; ans :longint; procedure swap(var a,b:longint); var c :longint; begin c:=a; a:=b; b:=c; end; procedure left_rotate(var t:longint); var k :longint; begin k:=b_right[t]; b_right[t]:=b_left[k]; b_left[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1; t:=k; end; procedure right_rotate(var t:longint); var k :longint; begin k:=b_left[t]; b_left[t]:=b_right[k]; b_right[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1; t:=k; end; procedure maintain(var t:longint;flag:boolean); begin if not flag then begin if b_size[b_left[b_left[t]]]>b_size[b_right[t]] then right_rotate(t) else if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then begin left_rotate(b_left[t]); right_rotate(t); end else exit; end else begin if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then left_rotate(t) else if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then begin right_rotate(b_right[t]); left_rotate(t); end else exit; end; maintain(b_left[t],false); maintain(b_right[t],true); maintain(t,true); maintain(t,false); end; procedure insert(var t:longint;v:longint); begin if t=0 then begin inc(tot); t:=tot; b_size[t]:=1; b_left[t]:=0; b_right[t]:=0; b_key[t]:=v; end else begin inc(b_size[t]); if v<b_key[t] then insert(b_left[t],v) else insert(b_right[t],v); maintain(t,v>=b_key[t]); end; end; function b_delete(var t:longint;v:longint):longint; begin dec(b_size[t]); if (b_key[t]=v) or (v>b_key[t]) and (b_right[t]=0) or (v<b_key[t]) and (b_left[t]=0) then begin b_delete:=b_key[t]; if (b_left[t]=0) or (b_right[t]=0) then t:=b_left[t]+b_right[t] else b_key[t]:=b_delete(b_left[t],v+1); end else if v>=b_key[t] then exit(b_delete(b_right[t],v)) else exit(b_delete(b_left[t],v)); end; procedure build(x,l,r:longint); var mid :longint; i :longint; begin t[x].left:=l; t[x].right:=r; t[x].root:=0; for i:=l to r do insert(t[x].root,high[i]); if l=r then exit; with t[x] do mid:=(left+right) div 2; build(2*x,l,mid); build(2*x+1,mid+1,r); end; function b_less(var t:longint;v:longint):longint; begin if t=0 then exit(0); if b_key[t]>=v then exit(b_less(b_left[t],v)) else exit(b_size[b_left[t]]+1+b_less(b_right[t],v)); end; function less(x,l,r,v:longint):longint; var mid :longint; begin if (t[x].left=l) and (t[x].right=r) then exit(b_less(t[x].root,v)); with t[x] do mid:=(left+right) div 2; if mid<l then exit(less(2*x+1,l,r,v)) else if mid>=r then exit(less(2*x,l,r,v)) else exit(less(2*x,l,mid,v)+less(2*x+1,mid+1,r,v)); end; function b_greater(var t:longint; v:longint):longint; begin if t=0 then exit(0); if b_key[t]<=v then exit(b_greater(b_right[t],v)) else exit(b_size[b_right[t]]+1+b_greater(b_left[t],v)); end; function greater(x,l,r,v:longint):longint; var mid :longint; begin if (t[x].left=l) and (t[x].right=r) then exit(b_greater(t[x].root,v)); with t[x] do mid:=(left+right) div 2; if mid<l then exit(greater(2*x+1,l,r,v)) else if mid>=r then exit(greater(2*x,l,r,v)) else exit(greater(2*x,l,mid,v)+greater(2*x+1,mid+1,r,v)); end; procedure change(x,y,v:longint); var mid :longint; begin insert(t[x].root,v); if (t[x].left=t[x].right) then exit; with t[x] do mid:=(left+right) div 2; if mid<y then change(2*x+1,y,v) else change(2*x,y,v); end; procedure delete(x,y,v:longint); var mid :longint; begin b_delete(t[x].root,v); if (t[x].left=t[x].right) then exit; with t[x] do mid:=(left+right) div 2; if mid<y then delete(2*x+1,y,v) else delete(2*x,y,v); end; procedure init; var i :longint; begin read(n); for i:=1 to n do read(high[i]); build(1,1,n); end; procedure main; var i :longint; x, y :longint; begin read(m); for i:=1 to n-1 do ans:=ans+less(1,i+1,n,high[i]); writeln(ans); for i:=1 to m do begin read(x,y); if (x=y) or (high[x]=high[y]) then begin writeln(ans); continue; end; if x>y then swap(x,y); if high[x]<high[y] then inc(ans) else dec(ans); if x+1<>y then begin ans:=ans-less(1,x+1,y-1,high[x]); ans:=ans+greater(1,x+1,y-1,high[x]); ans:=ans+less(1,x+1,y-1,high[y]); ans:=ans-greater(1,x+1,y-1,high[y]); end; delete(1,x,high[x]); change(1,x,high[y]); delete(1,y,high[y]); change(1,y,high[x]); swap(high[x],high[y]); writeln(ans); end; end; begin init; main; end.