zoukankan      html  css  js  c++  java
  • BZOJ1058:[ZJOI2007]报表统计(Splay,堆)

    Description

      小Q的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小Q希望可以帮妈妈分担一些工
    作,作为她的生日礼物之一。经过仔细观察,小Q发现统计一张报表实际上是维护一个可能为负数的整数数列,并
    且进行一些查询操作。在最开始的时候,有一个长度为N的整数序列,并且有以下三种操作: INSERT i k 在原数
    列的第i个元素后面添加一个新元素k; 如果原数列的第i个元素已经添加了若干元素,则添加在这些元素的最后(
    见下面的例子) MIN_GAP 查询相邻两个元素的之间差值(绝对值)的最小值 MIN_SORT_GAP 查询所有元素中最接
    近的两个元素的差值(绝对值) 例如一开始的序列为 5 3 1 执行操作INSERT 2 9将得到: 5 3 9 1 此时MIN_GAP
    为2,MIN_SORT_GAP为2。 再执行操作INSERT 2 6将得到: 5 3 9 6 1 注意这个时候原序列的第2个元素后面已经
    添加了一个9,此时添加的6应加在9的后面。这个时候MIN_GAP为2,MIN_SORT_GAP为1。于是小Q写了一个程序,使
    得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

    Input

      第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。第二行为N个整数,为初始序列。接下来
    的M行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无多余空格或者空行)。

    Output

      对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。

    Sample Input

    3 5
    5 3 1
    INSERT 2 9
    MIN_SORT_GAP
    INSERT 2 6
    MIN_GAP
    MIN_SORT_GAP

    Sample Output

    2
    2
    1

    HINT

    N , M ≤500000 对于所有的数据,序列内的整数不超过5*10^8。

    Solution

    操作1用splay维护区间
    操作2在进行操作1的时候从堆里删除旧的相邻值然后插入两个新的相邻值,
    然后在到2的时候输出堆顶
    注意可删除堆的操作(将删除的数放到del堆里,当两堆堆顶相同就pop
    操作3再开一个splay维护数就好了,每次查询下前驱后继,开个堆维护下最小值

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 #include<queue>
      6 #include<algorithm>
      7 #define N (2000000+1000)
      8 using namespace std;
      9 int last[N],Val[N],Father[N],Son[N][2],ins[N],Cnt[N],Size[N];
     10 int INF,n,m,a[N],sz=1000000,SZ,ROOT,root;
     11 priority_queue<int,vector<int>,greater<int> >ans;
     12 priority_queue<int,vector<int>,greater<int> >del;
     13 priority_queue<int,vector<int>,greater<int> >minnum;
     14 
     15 int Get(int x){return Son[Father[x]][1]==x;}
     16 void Update(int x){Size[x]=Cnt[x]+Size[Son[x][0]]+Size[Son[x][1]];}
     17 int Pre(int now){now=Son[now][0]; while (Son[now][1]) now=Son[now][1]; return now;}
     18 int Next(int now){now=Son[now][1]; while (Son[now][0]) now=Son[now][0]; return now;}
     19 
     20 void Rotate(int x)
     21 {
     22     int wh=Get(x);
     23     int fa=Father[x],fafa=Father[fa];
     24     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
     25     Son[fa][wh]=Son[x][wh^1]; Father[fa]=x;
     26     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
     27     Son[x][wh^1]=fa; Father[x]=fafa;
     28     Update(fa);    Update(x);
     29 }
     30 
     31 void Splay(int x,int tar,int &Root)
     32 {
     33     for (int fa; (fa=Father[x])!=tar; Rotate(x))
     34         if (Father[fa]!=tar)
     35             Rotate(Get(fa)==Get(x)?fa:x);
     36     if (!tar) Root=x;
     37 }
     38 
     39 void Insert(int x)
     40 {
     41     if (!root)
     42     {
     43         root=++sz;
     44         Size[sz]=Cnt[sz]=1;
     45         Val[sz]=x;
     46         return;
     47     }
     48     int now=root,fa=0;
     49     while (1)
     50     {
     51         if (x==Val[now])
     52         {
     53             Cnt[now]++;
     54             Update(now);
     55             Splay(now,0,root);
     56             return;
     57         }
     58         fa=now,now=Son[now][x>Val[now]];
     59         if (now==0)
     60         {
     61             Size[++sz]=Cnt[sz]=1;
     62             Val[sz]=x;
     63             Father[sz]=fa;
     64             Son[fa][x>Val[fa]]=sz;
     65             Splay(sz,0,root);
     66             return;
     67         }
     68     }
     69 }
     70 
     71 int Build(int l,int r,int fa)
     72 {
     73     if (l>r) return 0;
     74     int mid=(l+r)>>1;
     75     Size[mid]=Cnt[mid]=1;
     76     Val[mid]=a[mid];
     77     Father[mid]=fa;
     78     Son[mid][0]=Build(l,mid-1,mid);
     79     Son[mid][1]=Build(mid+1,r,mid);
     80     return mid;
     81     
     82 }
     83 int Findx(int x)
     84 {
     85     int now=ROOT;
     86     while (1)
     87         if (x<=Size[Son[now][0]])
     88             now=Son[now][0];
     89         else
     90         {
     91             x-=Size[Son[now][0]];
     92             if (x<=Cnt[now])
     93             {
     94                 Splay(now,0,ROOT);
     95                 return now;
     96             }
     97             x-=Cnt[now];
     98             now=Son[now][1];
     99         }
    100 }
    101 int Split(int x,int y)
    102 {
    103     Splay(x,0,ROOT); Splay(y,x,ROOT);
    104     return y;
    105 }
    106 
    107 int main()
    108 {
    109     memset(&INF,0x3f,sizeof(INF));
    110     scanf("%d%d",&n,&m); SZ=n+5;
    111     for (int i=1;i<=n;++i)
    112         scanf("%d",&a[i+1]);
    113     a[1]=a[n+2]=INF;
    114     for (int i=1;i<=n+2;++i)
    115     {
    116         Insert(a[i]);
    117         if (Cnt[root]>1 && Val[root]!=INF) minnum.push(0);
    118         else
    119         {            
    120             int pre=Pre(root),next=Next(root);
    121             if (pre) minnum.push(abs(Val[root]-Val[pre]));
    122             if (next) minnum.push(abs(Val[root]-Val[next]));
    123         }
    124         if (i>1) ans.push(abs(a[i]-a[i-1]));
    125         last[i]=i;
    126     }
    127     ROOT=Build(1,n+2,0);
    128     sort(a+1,a+n+2+1);
    129     for (int i=3;i<=n+1;++i)
    130         minnum.push(abs(Val[i]-Val[i-1]));
    131     for (int i=1;i<=m;++i)
    132     {
    133         char opt[10]; int x,y;
    134         scanf("%s",opt);
    135         if (opt[4]=='R')
    136         {
    137             scanf("%d%d",&x,&y); x++;
    138             int p=Split(last[x],x+1);
    139             Val[++SZ]=y; Father[SZ]=p;
    140             Son[p][0]=SZ;
    141             ins[x]++;
    142             Size[SZ]=Cnt[SZ]=1;
    143             Splay(SZ,0,ROOT);
    144             last[x]=SZ;
    145             int pre=Pre(ROOT),next=Next(ROOT);
    146             del.push(abs(Val[pre]-Val[next]));
    147             ans.push(abs(Val[pre]-Val[SZ]));
    148             ans.push(abs(Val[next]-Val[SZ]));
    149             Insert(y);
    150             if (Cnt[root]>1) minnum.push(0);
    151             else
    152             {            
    153                 pre=Pre(root),next=Next(root);
    154                 minnum.push(abs(Val[root]-Val[pre]));
    155                 minnum.push(abs(Val[root]-Val[next]));
    156             }
    157         }
    158         if (opt[4]=='G')
    159         {
    160             while (!del.empty() && del.top()==ans.top())
    161                 del.pop(),ans.pop();
    162             printf("%d
    ",ans.top());
    163         }
    164         if (opt[4]=='S')
    165             printf("%d
    ",minnum.top());
    166     }
    167 }
  • 相关阅读:
    响应式布局,流式布局与固定布局
    垃圾回收机制
    形象讲解时间复杂度
    数据结构和算法简介
    数据结构之栈和队列
    十、str的索引、切片和str常用的操作方法(重点)
    九、基础数类型总览和str、int、bool之间的相互转化
    八、编码的初识和进阶
    七、格式化输出和运算符
    六、while循环
  • 原文地址:https://www.cnblogs.com/refun/p/8685636.html
Copyright © 2011-2022 走看看