考试的时候看见这道题,感觉自己能AC掉,然后就冲着正解去了。然后想了想数据结构,应该是平衡树。然而蒟蒻的我忘了平衡树怎么打了。。然后就根据自己的记忆和理解打了出来。然后我简单的以为相邻的用个链表就能解决。没想到gg了。因为插一个的时候多出来两个相邻差值,然后会删除掉原来的一个相邻差值。这下我就懵逼了。想了想我能用的数据结构,好像没有什么思路,然后就用了个优先队列。挂掉了。

其实全局差值最小比较好求,用平衡树求一个前驱(<=它的最大值)和后继(>=它的最小值)即可。

然后相邻差值,可以用线段树维护,以个数为下标,存的是差值。新差值的下标为n+i即可。因为我们要更新之后,直接查询总共的最小值,所以顺序不用管。

注意到的是,在插入一个数后,会使原来的差值消除,产生两个新的差值,不需要删除,只需一个替换掉原来的,一个在尾部插入。用last[]记录原位置最后一个数,fir[]记录原位置第一个数,再用id[]记录最后一个数的位置,方便替换。

例如数列 1 3 5 2 7

线段树储存  2 2 3 5

当在1 3之间插入5时,新产生差值4 覆盖2,在末尾插入新差值2

线段树储存 4 2 3 5 2

#include<cstdio>
#include<algorithm>
#include<queue>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
#define N 401000
#define inf 0x7fffffff
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
int n,m;
int read(){
  int x=0,f=1;
  char ch=getchar();
  while(ch<'0'||ch>'9'){
    if(ch=='-') f=-1;
    ch=getchar();
  }
  while(ch>='0'&&ch<='9'){
    x=(x<<3)+(x<<1)+ch-'0';
    ch=getchar();
  }
  return x*f;
}
struct xixi{
    int l,r,num;
}t[N];
struct haha{
    int l,r,rnd,num;

}tree[N];
int root,size;
void rturn(int &k){
    int t=tree[k].l;
    tree[k].l=tree[t].r;
    tree[t].r=k;
    k=t;
}
void lturn(int &k){
    int t=tree[k].r;
    tree[k].r=tree[t].l;
    tree[t].l=k;
    k=t;
}
void insert(int &k,int x){
    if(k==0){
        k=++size;
        tree[k].rnd=rand();
        tree[k].num=x;
    }
    if(x>tree[k].num){
        insert(tree[k].r,x);
        if(tree[tree[k].r].rnd<tree[k].rnd)
            lturn(k);
    }
    if(x<tree[k].num){
        insert(tree[k].l,x);
        if(tree[tree[k].l].rnd<tree[k].rnd)
            rturn(k);
    }
}
int pro=inf,sub=inf;
void query_pro(int &k,int num){
    if(k==0)
      return;
    if(num>tree[k].num){
        pro=tree[k].num;
        query_pro(tree[k].r,num);
    }
    else{
        if(num==tree[k].num){
            pro=tree[k].num;
        }
        else{
            query_pro(tree[k].l,num);
        }
    }
}
void query_sub(int &k,int num){
    if(k==0)
      return;
    if(num<tree[k].num){
        sub=tree[k].num;
        query_sub(tree[k].l,num);
    }
    else{
        if(num==tree[k].num){
            sub=tree[k].num;
        }
        else{
            query_sub(tree[k].r,num);
        }
    }
}
int ans3=inf;
int aabs(int x){
    if(x<0)
      return -x;
    return x;
}
void build(int l,int r,int k){
    t[k].l=l;
    t[k].r=r;
    if(l==r){
        t[k].num=inf;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
}
void change(int pos,int num,int k){
    if(t[k].l==t[k].r){
        t[k].num=num;
        return;
    }
    if(pos<=t[k*2].r){
        change(pos,num,k*2);
    }
    else{
        change(pos,num,k*2+1);
    }
    t[k].num=min(t[k*2].num,t[k*2+1].num);
}
int query(int l,int r,int k){
    if(t[k].l==l&&t[k].r==r){
        return t[k].num;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if(r<=mid){
        return query(l,r,k*2);
    }
    else{
        if(l>mid)
            return query(l,r,k*2+1);
        else
            return min(query(l,mid,k*2),query(mid+1,r,k*2+1));
    }
}
int id[N],ji,last[N],fir[N];
int main(){
    //freopen("love.in","r",stdin);
    //freopen("love.out","w",stdout);
    n=read();m=read();
    build(0,n+m-1,1);
    pos(i,1,n){
        int x=read();
        fir[i]=x;last[i]=x;
        query_pro(root,x);
        query_sub(root,x);
        int temp=min(aabs(x-pro),aabs(x-sub));
        ans3=min(ans3,temp);
        insert(root,x);
    }
    pos(i,1,n-1){
        int temp=aabs(fir[i]-fir[i+1]);
        id[i]=++ji;
        change(ji,temp,1);
    }
    pos(i,1,m){
        char s[50];
        scanf("%s",s);
        if(s[4]=='G'){
            printf("%d\n",query(0,ji,1));
        }
        if(s[4]=='S'){
            printf("%d\n",ans3);
        }
        if(s[4]=='R'){
            int x=read(),y=read();
            query_pro(root,y);
            query_sub(root,y);
            int temp=min(aabs(y-pro),aabs(y-sub));
            ans3=min(ans3,temp);
            insert(root,y);

            if(x!=n){
                int b=aabs(last[x]-y),c=aabs(y-fir[x+1]);
                //cout<<"b="<<b<<"   c="<<c<<endl;
                change(id[x],b,1);
                last[x]=y;
                id[x]=++ji;
                change(id[x],c,1);
            }
            if(x==n){
                int b=aabs(last[x]-y);
                id[x]=++ji;
                change(id[x],b,1);
            }

        }
    }
    //pos(i,1,n)
      //cout<<id[i]<<endl;
    //pos(i,1,ji){
        //cout<<"query="<<query(0,4,1)<<endl;
    //}
    return 0;
}

  

[BZOJ 1058][ZJOI 2007]报表统计 平衡树+线段树的更多相关文章

  1. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  2. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  3. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  4. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  5. BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)

    LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...

  6. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  7. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  8. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  9. 3682: Phorni 后缀平衡树 线段树

    国际惯例的题面: 考虑如果没有强制在线我们能怎么水掉这个题,先构造出字符串,各种方法求一下后缀数组,然后线段树维护区间rank最小的位置即可.然而他要求强制在线,支持插入后缀,并比较后缀大小(求ran ...

随机推荐

  1. Mathematica学习笔记2

    导入文件中的矩阵 mat = Import["...", "Table"] 转化为向量矩阵(元素为数对) data = Table[{mat[[i, j]], ...

  2. C# 校验帮助类-正则表达式

    一.简介 很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的.所以我把自己整理的校验帮助类分享处理,在这里分享一下,给自己留 ...

  3. JS之正则表达式

    一.正则表达的目标: 1.使用表单事件和脚本函数实现表单验证 2.使用String对象和文本框控件常用属性和方法实现客户端验证 二.什么需要表单验证: 1.表单元素是否为空 2.用户名和密码 3.E- ...

  4. 使用Homebrew安装MySQL

    安装命令: brew install mysql 安装完成之后,启动mysql: mysql.server start 发现无此命令: command not found 首先,检查是否是安装了.重新 ...

  5. Python 文件对象

    Python 文件对象 1) 内置函数 open() 用于打开和创建文件对象 open(name,[,mode[,bufsize]]) 文件名.模式.缓冲区参数 mode: r 只读 w 写入 a 附 ...

  6. Linux配置LNMP环境(一)配置Nginx

    注意:配置版本nginx-1.12.0,使用虚拟机安装linux.教程中的下载地址可能有变化.注意(在您看本教程之前首先需要对linux的基本操作熟悉) 1.  先cd到/usr/local/src ...

  7. VB6之WebBrowser控件

    UI短手或者GDI+用烦的童鞋可以借用WebBrowser打造漂亮的程序界面,只需要下载一个好看点的html代码就够了. 引用: Microsoft Html Object Library 部件: M ...

  8. React环境配置

    现在开始配置一个基础项目. 创建项目文件夹:C:\Users\Danny\Desktop\React npm init 创建package.json文件 下面的所有安装,都是--save-dev,因为 ...

  9. C实现dos图文菜单程序实例

      前言 公司一台服务器是novell环境,文件管理是基于dos6.22的,客户端启动需要一个图文菜单.   实现    编程环境:汉化版TC2.0 菜单基本功能:显示提示项.显示dbf中的行情信息. ...

  10. HTML5头部标签中<meta>常用信息

    整理一些平时常用的,方便查阅 <!-- 字体编码 --> <meta charset="utf-8" /> <!-- 关键字 --> <m ...