zoukankan      html  css  js  c++  java
  • bzoj 2120 线段树套平衡树

    先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心。。。。。

    首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有,

    但是能给我们一个思路的启发

    我们先考虑没有修改,只有区间询问

    内个我下面的糖果是画笔的意思。。。我也不知道咋着题就读错了。。。。

    那么对于一个糖果i,假设他的颜色是col,那么我们找到col颜色上一次出现的位置,为color[i],

    那么对于一个区间L R里的color值,我们要找不同的颜色,那么假设一种颜色在L R里出现多次

    那么这些糖果的color值除了最先出现的以外,剩下的color值都大于等于L,也就是我们要找在区间

    L R里的color值比L小的个数就行了。我们可以用线段树套平衡树来比较容易的实现这一过程

    //时间复杂度是O(nlog^2(n))的,1878做不了

    树套树就相当于维护color数组用的

    那么我们在修改一个位置的颜色的时候,假设把位置I的颜色改为y,原来的颜色为x

    那么我们需要修改的是

    i位置后面第一个颜色为X的color值改为i的color值

    I位置的color值改为i前面最后一个颜色为Y的位置

    I位置后面第一个颜色为Y的color值改为I

    这样就行了,那么我们为了快速找到“I位置后面第一个颜色为X的糖果的位置”,需要对于每种颜色

    建一颗平衡树,关键字为位置,只需要找到后继就行了

    /**************************************************************
        Problem: 2120
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:2024 ms
        Memory:16280 kb
    ****************************************************************/
     
    //By BLADEVIL
    type
        rec                     =record
            left, right, root   :longint;
        end;
     
    var
        n, m                    :longint;
        a                       :array[0..10010] of longint;
        t                       :array[0..30010] of rec;
        c_pred, c_root          :array[0..1000010] of longint;
        color                   :array[0..10010] of longint;
        tot                     :longint;
        b_left, b_right         :array[0..500000] of longint;
        b_size, b_key           :array[0..500000] of longint;
     
    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_left[t]:=0;
            b_right[t]:=0;
            b_size[t]:=1;
            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;
         
    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,color[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;
     
    procedure init;
    var
        i                       :longint;
    begin
        read(n,m);
        for i:=1 to n do read(a[i]);
        for i:=1 to n do
        begin
            color[i]:=c_pred[a[i]];
            c_pred[a[i]]:=i;
        end;
        for i:=1 to n do c_root[a[i]]:=0;
        for i:=1 to n do
            insert(c_root[a[i]],i);
        build(1,1,n);
    end;
     
    function select(t,v:longint):longint;
    begin
        if t=0 then exit(0);
        if b_key[t]>=v then
            select:=select(b_left[t],v) else
            select:=select(b_right[t],v)+b_size[b_left[t]]+1;
    end;
     
    function query(x,l,r,y:longint):longint;
    var
        mid                     :longint;
    begin
        if (t[x].left=l) and (t[x].right=r) then
        begin
            query:=select(t[x].root,y);
            exit;
        end;
        with t[x] do mid:=(left+right) div 2;
        if l>mid then query:=query(x*2+1,l,r,y) else
        if r<=mid then query:=query(x*2,l,r,y) else
        query:=query(x*2,l,mid,y)+query(x*2+1,mid+1,r,y);
    end;
     
    procedure ask(l,r:longint);
    begin
        writeln(query(1,l,r,l));
    end;
     
    function 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
            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]:=delete(b_left[t],v+1);
        end else
            if v>b_key[t] then delete:=delete(b_right[t],v) else delete:=delete(b_left[t],v);
    end;
     
    procedure t_change(x,y,z,xx:longint);
    var
        mid                     :longint;
    begin
        delete(t[x].root,y);
        insert(t[x].root,z);
        if t[x].left=t[x].right then exit;
        with t[x] do mid:=(left+right) div 2;
        if xx>mid then t_change(2*x+1,y,z,xx) else
            t_change(2*x,y,z,xx);
    end;
     
    function pred(t,v:longint):longint;
    begin
        if t=0 then exit(0);
        if b_key[t]>=v then pred:=pred(b_left[t],v) else
        begin
            pred:=pred(b_right[t],v);
            if pred=0 then pred:=b_key[t];
        end;
    end;
     
    function succ(t,v:longint):longint;
    begin
        if t=0 then exit(-1);
        if b_key[t]<=v then succ:=succ(b_right[t],v) else
        begin
            succ:=succ(b_left[t],v);
            if succ=-1 then succ:=b_key[t];
        end;
    end;
     
    procedure change(x,y:longint);
    var
        w1, w2, w3              :longint;
         
    begin
        if a[x]=y then exit;
        w1:=a[x];
        w2:=pred(c_root[w1],x);
        w3:=succ(c_root[w1],x);
        if w3<>-1 then t_change(1,x,w2,w3);
        delete(c_root[w1],x);
        w1:=w2;
        w3:=succ(c_root[y],x);
        w2:=pred(c_root[y],x);
        if w3<>-1 then t_change(1,w2,x,w3);
        t_change(1,w1,w2,x);
        a[x]:=y;
        insert(c_root[y],x);
    end;
     
    procedure main;
    var
        i                       :longint;
        ch                      :char;
        x, y                    :longint;
    begin
        readln;
        for i:=1 to m do
        begin
            read(ch);
            readln(x,y);
            if ch='Q' then
                ask(x,y) else
                change(x,y);
        end;
         
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    【刷题-LeetCode】204. Count Primes
    【刷题-LeetCode】205. Isomorphic Strings
    【刷题-LeetCode】207. Course Schedule
    剑指offer题解——找出数组中重复的数字
    关于c++中vector操作
    动态规划算法
    分治算法
    从零学python——组合数据类型
    从零学python—PyInstaller库的介绍
    从零学python——代码复用与函数递归
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3468038.html
Copyright © 2011-2022 走看看