• bzoj 1058 bst


      因为是数列的维护,所以我们可以考虑用splay来维护,每次在x插入的时候就在x+1前面插入就行了,然后用bst来维护两问的答案,但是应该会tle。我们来考虑这个问题的性质,首先因为这个数列没有删除操作,所以每个数插入进去之后就不会出来了,换句话说,就是假设insert(x,y)那么y这个值和前面的那个数可以更新相邻差值的答案,且这个不会因为其他的插入操作而使得这个差值消失(消失值类似(x,y)插入,那么之前在x处插入的点与x+1的差值会消失),所以我们只需要存储每个位置最后插入的数,那么对于一个插入(x,y)我们只需要判断x位置是否插入过值然后讨论就行了。那么对于另一个全局差值的更新我们只需要用bst维护所有插入的数,每插入一个数就找前驱后继来更新答案就行了。因为这个答案是递减的,所以当答案为0的时候不用更新就行了,这样大概可以快3-4s。

      反思:很早的时候用pascal写了splay的,满满的tle,然后转了C++之后用的set和map,快了好多,也好写了好多= =

    /**************************************************************
        Problem: 1058
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:9924 ms
        Memory:40700 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <set>
    #define maxn 1000010
    #define inf (~0U>>1)
     
    using namespace std;
     
    int n,m,ans;
    int a[maxn],b[maxn];
    char c[20];
    map<int,int>ms;
    set<int>bt;
     
    void update(int x){
        if (bt.count(x)) {
            ans=0; return;
        }
        set<int>::iterator p=bt.upper_bound(x);
        if (p!=bt.end()) ans=min(ans,abs(*p-x));//,printf("%d->%d ",x,*p);
        --p;
        if (*p!=-inf) ans=min(ans,abs(*p-x));//,printf("%d<-%d",x,*p); printf("
    ");
        bt.insert(x);
    }
     
    void insert(int x){
        map<int,int>::iterator p=ms.find(x);
        if (p!=ms.end()) p->second++; else ms.insert(pair<int,int>(x,1));
    }
     
    void erase(int x){
        map<int,int>::iterator p=ms.find(x);
        if (p->second==1) ms.erase(p); else p->second--;
    }
     
    void printbt(){
        for (set<int>::iterator p=bt.begin();p!=bt.end();p++) printf("%d ",*p); printf("
    ");
    }
     
    void printms(){
        for (map<int,int>::iterator p=ms.begin();p!=ms.end();p++) printf("|%d %d
    ",p->first,p->second);
    }
     
    int main(){
        ans=inf; bt.insert(-inf);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<n;i++) insert(abs(a[i]-a[i+1]));
        for (int i=1;i<=n;i++) { 
            if (bt.count(a[i])) {
                ans=0; break;
            }
            update(a[i]);
        }
        //printms(); printbt();
        while (m--){
            scanf("%s",&c);
            if (c[0]=='I'){
                int x,y;
                scanf("%d%d",&x,&y);
                if (x==n){
                    if (b[x]) insert(abs(b[x]-y)); else insert(abs(a[x]-y));
                } else {
                    if (b[x]){
                        erase(abs(b[x]-a[x+1]));
                        insert(abs(b[x]-y)); insert(abs(a[x+1]-y));
                    } else {
                        erase(abs(a[x]-a[x+1]));
                        insert(abs(a[x]-y)); insert(abs(a[x+1]-y));
                    }
                }
                b[x]=y;
                if (ans) update(y);
            } else
            if (c[4]=='G') {
                printf("%d
    ",ms.begin()->first);
            } else printf("%d
    ",ans);
        }
        return 0;
    }
    /**************************************************************
        Problem: 1058
        User: BLADEVIL
        Language: Pascal
        Result: Time_Limit_Exceed
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m                    :longint;
        root, sroot             :longint;
        father, size            :array[-1..1000010] of longint;
        tree, a                 :array[-1..1000010] of int64;
        son                     :array[-1..1000010,0..1] of longint;
        numt, t, st             :longint;
        tot                     :longint;
        left, right, b_size     :array[0..4000010] of longint;
        key                     :array[0..4000010] of int64;
        print                   :int64;
         
    function abs(x:int64):int64;
    begin
        if x<0 then exit(-x) else exit(x);
    end;
         
    function min(a,b:int64):int64;
    begin
        if a>b then min:=b else min:=a;
    end;
         
    procedure update(x:longint);
    begin
        size[x]:=size[son[x][0]]+size[son[x][1]]+1;
    end;
         
    function build(l,r:longint):longint;
    var
        mid                     :longint;
    begin
        mid:=(l+r)>>1;
        build:=mid;
        tree[mid]:=a[mid];
        if mid-1>=l then
        begin
            son[mid][0]:=build(l,mid-1);
            father[son[mid][0]]:=mid;
        end;
        if mid+1<=r then
        begin
            son[mid][1]:=build(mid+1,r);
            father[son[mid][1]]:=mid;
        end;
        update(mid);
    end;
     
    procedure rotate(x,y:longint);
    var
        f                       :longint;
    begin
        f:=father[x];
        son[f][y]:=son[x][y xor 1];
        father[son[x][y xor 1]]:=f;
        if f=root then root:=x else
            if f=son[father[f]][0] then
                son[father[f]][0]:=x else
            if f=son[father[f]][1] then
                son[father[f]][1]:=x;
        son[x][y xor 1]:=f;
        father[x]:=father[f];
        father[f]:=x;
        update(f);
        update(x);
    end;
     
    procedure splay(x,y:longint);
    var
        u, v                    :longint;
    begin
        while father[x]<>y do
        if father[father[x]]=y then
            rotate(x,ord(x=son[father[x]][1])) else
        begin
            if x=son[father[x]][0] then u:=1 else u:=-1;
            if father[x]=son[father[father[x]]][0] then v:=1 else v:=-1;
            if u*v=1 then
            begin
                rotate(father[x],ord(x=son[father[x]][1]));
                rotate(x,ord(x=son[father[x]][1]));
            end else
            begin
                rotate(x,ord(x=son[father[x]][1]));
                rotate(x,ord(x=son[father[x]][1]));
            end;        
        end;
        update(x);
    end;
     
    function find(x:int64):int64;
    var
        t                       :longint;
    begin
        t:=root;
        while true do
        begin
            if size[son[t][0]]+1=x then exit(t) else
            if size[son[t][0]]+1>x then t:=son[t][0] else
            begin
                x:=x-(size[son[t][0]]+1);
                t:=son[t][1];
            end;
        end;
    end;
     
    procedure left_rotate(var t:longint);
    var
        k                       :longint;
    begin
        k:=right[t];
        right[t]:=left[k];
        left[k]:=t;
        b_size[k]:=b_size[t];
        b_size[t]:=b_size[left[t]]+b_size[right[t]]+1;
        t:=k;
    end;
     
    procedure right_rotate(var t:longint);
    var
        k                       :longint;
    begin
        k:=left[t];
        left[t]:=right[k];
        right[k]:=t;
        b_size[k]:=b_size[t];
        b_size[t]:=b_size[left[t]]+b_size[right[t]]+1;
        t:=k;
    end;
     
    procedure maintain(var t:longint;flag:boolean);
    begin
        if not flag then
        begin
            if b_size[left[left[t]]]>b_size[right[t]] then
                right_rotate(t) else
            if b_size[right[left[t]]]>b_size[right[t]] then
            begin
                left_rotate(left[t]);
                right_rotate(t);
            end else exit;
        end else
        begin
            if b_size[right[right[t]]]>b_size[left[t]] then
                left_rotate(t) else
            if b_size[left[right[t]]]>b_size[left[t]] then
            begin
                right_rotate(right[t]);
                left_rotate(t);
            end else exit;
        end;
         
        maintain(left[t],false);
        maintain(right[t],true);
        maintain(t,true);
        maintain(t,false);
    end;
     
    procedure insert(var t:longint;v:int64);
    begin
        if t=0 then
        begin
            inc(tot);
            t:=tot;
            key[t]:=v;
            b_size[t]:=1;
            left[t]:=0;
            right[t]:=0;
        end else
        begin
            b_size[t]:=b_size[t]+1;
            if v<key[t] then insert(left[t],v) else insert(right[t],v);
            maintain(t,v>=key[t]);
        end;
    end;
     
    function pred(var t:longint;v:int64):int64;
    begin
        if t=0 then exit(maxlongint>>1);
        if key[t]>v then pred:=pred(left[t],v) else
        begin
            pred:=pred(right[t],v);
            if pred=maxlongint>>1 then exit(key[t]);
        end;
    end;
     
    function succ(var t:longint;v:int64):int64;
    begin
        if t=0 then exit(maxlongint>>1);
        if key[t]<v then succ:=succ(right[t],v) else
        begin
            succ:=succ(left[t],v);
            if succ=maxlongint>>1 then exit(key[t]);
        end;
    end;
     
    function delete(var t:longint;v:int64):int64;
    begin
        b_size[t]:=b_size[t]-1;
        if (key[t]=v) or (v>key[t]) and (right[t]=0) or (v<key[t]) and (left[t]=0) then
        begin
            delete:=key[t];
            if (left[t]=0) or (right[t]=0) then
                t:=left[t]+right[t] else
                key[t]:=delete(left[t],v+1);
        end else
            if v>=key[t] then delete:=delete(right[t],v) else delete:=delete(left[t],v);
    end;
     
    procedure change(x:longint;y:int64);
    var
        q, p                    :int64;
         
    begin
        splay(x,sroot);
        p:=size[son[root][0]];
        p:=find(p);
        splay(p,root);
        delete(t,abs(tree[p]-tree[root]));
        insert(t,abs(y-tree[p]));
        insert(t,abs(y-tree[root]));
        inc(n);
        a[n]:=y;
        tree[n]:=y;
        son[son[root][0]][1]:=n;
        father[n]:=son[root][0];
        size[n]:=1;
        update(son[root][0]);
        update(root);
        p:=pred(numt,y);
        q:=succ(numt,y);
        if p=maxlongint>>1 then insert(st,abs(q-y)) else
            if q=maxlongint>>1 then insert(st,abs(p-y)) else
            insert(st,min(abs(p-y),abs(q-y)));
        insert(numt,y);
    end;
     
    function mini(var t:longint):int64;
    begin
        if left[t]=0 then exit(key[t]) else exit(mini(left[t]));    
    end;
     
    procedure init;
    var
        i                       :longint;
        x, y                    :int64;
    begin  
        readln(n,m);
        for i:=1 to n do read(a[i]);
        readln;
        numt:=0;
         
        st:=0;
        for i:=1 to n do
        begin
            x:=succ(numt,a[i]);
            y:=pred(numt,a[i]);
            insert(numt,a[i]);
            if x=maxlongint>>1 then insert(st,abs(y-a[i])) else
            if y=maxlongint>>1 then insert(st,abs(x-a[i])) else
            insert(st,min(abs(x-a[i]),abs(y-a[i])));
        end;
         
        t:=0;
        for i:=1 to n-1 do
            insert(t,abs(a[i+1]-a[i]));
         
        fillchar(son,sizeof(son),255);
        sroot:=-1;
        inc(n);
        root:=build(0,n);
        father[root]:=sroot;
    end;
     
    procedure main;
    var
        i                       :longint;
        s                       :ansistring;
        ch                      :char;
        x                       :longint;
        y                       :int64;
         
    begin
        print:=maxlongint>>1;
        for i:=1 to m do
        begin
            read(ch);
            if ch='I' then
            begin
                s:='';
                while ch<>' ' do
                begin
                    s:=s+ch;
                    read(ch);
                end;
                readln(x,y);
                change(x+1,y);
            end else
            begin
                readln(s);
                if s[4]='S' then
                begin
                    if print=0 then
                    begin
                        writeln(0);
                    end else
                    begin
                        if mini(st)<print then print:=mini(st);
                        writeln(print);
                    end;
                end else
                    writeln(mini(t));
            end;
        end;
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    BGP deterministic-med & compare-med
    BGP Always-compare-med & Deterministic-med
    BGP实验 MED , Cyrus
    BGP Lab AS-path prepend last-as
    详解C/C++中volatile关键字
    38、hashtable中解决冲突有哪些方法?
    37、STL中unordered_map和map的区别和应用场景
    36、set和map的区别,multimap和multiset的区别
    35、STL中map的实现
    34、STL中set的实现?
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3574366.html
Copyright © 2020-2023  润新知