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.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3494564.html