因为是数列的维护,所以我们可以考虑用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[];
map<int,int>ms;
set<int>bt;
 
void update(int x){
    if (bt.count(x)) {
        ans=; 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("\n");
    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,));
}
 
void erase(int x){
    map<int,int>::iterator p=ms.find(x);
    if (p->second==) ms.erase(p); else p->second--;
}
 
void printbt(){
    for (set<int>::iterator p=bt.begin();p!=bt.end();p++) printf("%d ",*p); printf("\n");
}
 
void printms(){
    for (map<int,int>::iterator p=ms.begin();p!=ms.end();p++) printf("|%d %d\n",p->first,p->second);
}
 
int main(){
    ans=inf; bt.insert(-inf);
    scanf("%d%d",&n,&m);
    for (int i=;i<=n;i++) scanf("%d",&a[i]);
    for (int i=;i<n;i++) insert(abs(a[i]-a[i+]));
    for (int i=;i<=n;i++) {
        if (bt.count(a[i])) {
            ans=; break;
        }
        update(a[i]);
    }
    //printms(); printbt();
    while (m--){
        scanf("%s",&c);
        if (c[]=='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+]));
                    insert(abs(b[x]-y)); insert(abs(a[x+]-y));
                } else {
                    erase(abs(a[x]-a[x+]));
                    insert(abs(a[x]-y)); insert(abs(a[x+]-y));
                }
            }
            b[x]=y;
            if (ans) update(y);
        } else
        if (c[]=='G') {
            printf("%d\n",ms.begin()->first);
        } else printf("%d\n",ans);
    }
    return ;
}
/**************************************************************
    Problem:
    User: BLADEVIL
    Language: Pascal
    Result: Time_Limit_Exceed
****************************************************************/
 
//By BLADEVIL
var
    n, m                    :longint;
    root, sroot             :longint;
    father, size            :array[-..] of longint;
    tree, a                 :array[-..] of int64;
    son                     :array[-..,..] of longint;
    numt, t, st             :longint;
    tot                     :longint;
    left, right, b_size     :array[..] of longint;
    key                     :array[..] of int64;
    print                   :int64;
     
function abs(x:int64):int64;
begin
    if x< 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][]]+size[son[x][]]+;
end;
     
function build(l,r:longint):longint;
var
    mid                     :longint;
begin
    mid:=(l+r)>>;
    build:=mid;
    tree[mid]:=a[mid];
    if mid->=l then
    begin
        son[mid][]:=build(l,mid-);
        father[son[mid][]]:=mid;
    end;
    if mid+<=r then
    begin
        son[mid][]:=build(mid+,r);
        father[son[mid][]]:=mid;
    end;
    update(mid);
end;
 
procedure rotate(x,y:longint);
var
    f                       :longint;
begin
    f:=father[x];
    son[f][y]:=son[x][y xor ];
    father[son[x][y xor ]]:=f;
    if f=root then root:=x else
        if f=son[father[f]][] then
            son[father[f]][]:=x else
        if f=son[father[f]][] then
            son[father[f]][]:=x;
    son[x][y xor ]:=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]][])) else
    begin
        if x=son[father[x]][] then u:= else u:=-;
        if father[x]=son[father[father[x]]][] then v:= else v:=-;
        if u*v= then
        begin
            rotate(father[x],ord(x=son[father[x]][]));
            rotate(x,ord(x=son[father[x]][]));
        end else
        begin
            rotate(x,ord(x=son[father[x]][]));
            rotate(x,ord(x=son[father[x]][]));
        end;       
    end;
    update(x);
end;
 
function find(x:int64):int64;
var
    t                       :longint;
begin
    t:=root;
    while true do
    begin
        if size[son[t][]]+=x then exit(t) else
        if size[son[t][]]+>x then t:=son[t][] else
        begin
            x:=x-(size[son[t][]]+);
            t:=son[t][];
        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]]+;
    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]]+;
    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= then
    begin
        inc(tot);
        t:=tot;
        key[t]:=v;
        b_size[t]:=;
        left[t]:=;
        right[t]:=;
    end else
    begin
        b_size[t]:=b_size[t]+;
        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= then exit(maxlongint>>);
    if key[t]>v then pred:=pred(left[t],v) else
    begin
        pred:=pred(right[t],v);
        if pred=maxlongint>> then exit(key[t]);
    end;
end;
 
function succ(var t:longint;v:int64):int64;
begin
    if t= then exit(maxlongint>>);
    if key[t]<v then succ:=succ(right[t],v) else
    begin
        succ:=succ(left[t],v);
        if succ=maxlongint>> then exit(key[t]);
    end;
end;
 
function delete(var t:longint;v:int64):int64;
begin
    b_size[t]:=b_size[t]-;
    if (key[t]=v) or (v>key[t]) and (right[t]=) or (v<key[t]) and (left[t]=) then
    begin
        delete:=key[t];
        if (left[t]=) or (right[t]=) then
            t:=left[t]+right[t] else
            key[t]:=delete(left[t],v+);
    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][]];
    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][]][]:=n;
    father[n]:=son[root][];
    size[n]:=;
    update(son[root][]);
    update(root);
    p:=pred(numt,y);
    q:=succ(numt,y);
    if p=maxlongint>> then insert(st,abs(q-y)) else
        if q=maxlongint>> 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]= then exit(key[t]) else exit(mini(left[t]));   
end;
 
procedure init;
var
    i                       :longint;
    x, y                    :int64;
begin  
    readln(n,m);
    for i:= to n do read(a[i]);
    readln;
    numt:=;
     
    st:=;
    for i:= to n do
    begin
        x:=succ(numt,a[i]);
        y:=pred(numt,a[i]);
        insert(numt,a[i]);
        if x=maxlongint>> then insert(st,abs(y-a[i])) else
        if y=maxlongint>> then insert(st,abs(x-a[i])) else
        insert(st,min(abs(x-a[i]),abs(y-a[i])));
    end;
     
    t:=;
    for i:= to n- do
        insert(t,abs(a[i+]-a[i]));
     
    fillchar(son,sizeof(son),);
    sroot:=-;
    inc(n);
    root:=build(,n);
    father[root]:=sroot;
end;
 
procedure main;
var
    i                       :longint;
    s                       :ansistring;
    ch                      :char;
    x                       :longint;
    y                       :int64;
     
begin
    print:=maxlongint>>;
    for i:= 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+,y);
        end else
        begin
            readln(s);
            if s[]='S' then
            begin
                if print= then
                begin
                    writeln();
                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.

bzoj 1058 bst的更多相关文章

  1. [BZOJ 1058] [ZJOI2007] 报表统计 【平衡树】

    题目链接:BZOJ - 1058 题目分析 这道题看似是需要在序列中插入一些数字,但其实询问的内容只与相邻的元素有关. 那么我们只要对每个位置维护两个数 Ai, Bi, Ai 就是初始序列中 i 这个 ...

  2. [BZOJ 1058] 报表统计

    Link: BZOJ 1058 传送门 Solution: 为了这道题今天下午一直都在和常数大战…… 1.对于询问1,我们记录每个数末位置的数$T[i]$和初始位置$S[i]$ 用平衡树维护所有差值, ...

  3. bzoj 1058 [ZJOI2007]报表统计(set)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1058 [题意] 一个序列,提供插入,查询相邻最小差值,查询任意最小差值的操作. [思路 ...

  4. BZOJ 1058: [ZJOI2007]报表统计( 链表 + set )

    这种题用数据结构怎么写都能AC吧...按1~N弄个链表然后每次插入时就更新答案, 用set维护就可以了... --------------------------------------------- ...

  5. bzoj 1058: [ZJOI2007]报表统计

    Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工 作,作为她的生日礼物之一.经过仔细观察,小Q发现统计一张报表实际上是维护一个 ...

  6. bzoj 1058: [ZJOI2007]报表统计 (Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1058 题面; 1058: [ZJOI2007]报表统计 Time Limit: 15 Sec ...

  7. AC日记——[ZJOI2007]报表统计 bzoj 1058

    1058 思路: 平衡树的题: 然而我的平衡树写一次炸一次QwQ: 而且各种tle: 所以stl水过: 代码: #include <set> #include <cstdio> ...

  8. BZOJ 1058

    服气!我果然就是个傻逼. 傻兮兮地感觉两个数之间的差距无需删除一些答案,妈个鸡就只加入了一些新的答案忘记了去掉无效的答案.我果然是傻逼,经验不足脑子笨... 这么水的题...不说了,说多了都是泪. 自 ...

  9. BZOJ 1058 报表统计 (STL)

    题解:数据结构的基本操作,用STL可以完美实现,就是比较慢…… #include <cstdio> #include <map> #include <set> #i ...

随机推荐

  1. linux的几个发行网站

     Red Hat: http://www.redhat.com  Fedora: http://fedoraproject.org/  Mandriva: http://www.mandriva ...

  2. cmd批处理中set /a和set /p的区别介绍

    在 SET 命令中添加了两个新命令行开关: SET /A expression SET /P variable=[promptString]/p 是让你输入/a 是指定一个变量等于一串运算字符 什么参 ...

  3. canvas drawImage 不显示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. HTML5 Web SQL 数据库总结

    Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs. 如果你是一个 Web 后端程序员,应该很容易理解 SQ ...

  5. openstack中间件message queue 与memcached环境部署

    为什么要安装中间件 组件间的通信使用的是REST API 而组件内部之间的通信则是使用的中间件 首先登陆openstack的官网查看官方文档 www.openstack.org 应为在部署一个架构之前 ...

  6. CodeForces - 704C

    题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 a 或者 a|b 亦或起来,每个变量最多出现两次(包括反变量) 嘴炮开始:每个变量最多出现两次,那么跟它相关联的变量 ...

  7. harbor1.4.0高可用部署

    一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Parent 构造函数成为 Children 的方法,然 ...

  8. POJ3498:March of the Penguins——题解

    最近的题解的故事背景割. 题目: 描述 在靠近南极的某处,一些企鹅站在许多漂浮的冰块上.由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上.企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃, ...

  9. 使用自己的数据集训练和测试"caffenet"

    主要步骤可参考: http://blog.csdn.net/u010194274/article/details/50575284 补充几点: 1. convert函数是ImageMagick包里面的 ...

  10. Android线程池ThreadPoolExecutor

    阿里巴巴Android开发手册[强制]新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor或者其他形式自定义的线程池),不允许在应用中自行显式创建线程说明:使 ...