勤快的love 枫

题目描述

小绝恋love 枫是一个出纳,经常需要做一些统计报表的工作。今天是绝恋love 枫的生日,小绝恋love 枫希望可以帮爸爸分担一些工作,作为他的生日礼物之一。经过仔细观察,小绝恋love 枫发现统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。在最开始的时候,有一个长度为的整数序列,并且有以下三种操作:INSERT i k 在原数列的第个元素后面添加一个新元素k;如果原数列的第个元素已经添加了若干元素,则添加在这些元素的最后(见下面的例子)

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。于是小绝恋love 枫写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

输入

第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。

第二行为个整数,为初始序列。

接下来的行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无

多余空格或者空行)。

输出

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

样例输入

3 55 3 1INSERT 2 9MIN_SORT_GAPINSERT 2 6MIN_GAPMIN_SORT_GAP

样例输出

221
第一问,维护相邻项的最小差值,支持插入和删除,可以用堆来维护,对于删除操作,可以见一个垃圾堆,这样每一步直接询问最小值时,比较当前堆和垃圾堆的top,while(q1.top()==q2.top()) q1.pop();q2.pop();
第二问,维护整个序列的最小值,可知最小差值一定出现在排序后的相邻项之间的差值中,对于某一个数,它的前一项就是前驱,后一项是后继,用treap维护
而且对于每一个元素后插入的数,只需要记录上一次插入该元素后的数,对应删除和插入
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#define N 100005
using namespace std;
int n,m,mi;
int pr[N],a[N];
struct  treap
{
     int l,r,w,v,rnd; 
}t[N];
int root,size,ans;
priority_queue<int, vector<int>, greater<int> > q1,q2;
void add(int x,int y){
     int t=0;
     if(pr[x]==-1){
        t=abs(a[x]-a[x+1]);  q2.push(t);
        t=abs(a[x]-y); q1.push(t);
        t=abs(a[x+1]-y);  q1.push(t);
     }
     else{
        t=abs(pr[x]-a[x+1]); q2.push(t);
        t=abs(pr[x]-y); q1.push(t);
        t=abs(y-a[x+1]); q1.push(t);
     }
     pr[x]=y;
}
void lturn(int &k)
{
     int p=t[k].r;
     t[k].r=t[p].l;
     t[p].l=k;
     k=p;
}
void rturn(int &k)
{
     int p=t[k].l;
     t[k].l=t[p].r;
     t[p].r=k;
     k=p;
}
void insert(int &k,int x)
{
     if(k==0){
        size++;k=size;
        t[k].w=1;t[k].v=x;t[k].rnd=rand();
        return ;
     }
     if(t[k].v==x) t[k].w++;
     else
      if(t[k].v<x){
         insert(t[k].r,x);
         if(t[t[k].r].rnd<t[k].rnd) lturn(k);
      }
      else{
         insert(t[k].l,x);
         if(t[t[k].l].rnd<t[k].rnd)  rturn(k);
      }
}
void pre(int k,int x)
{
     if(!k) return ;
     if(t[k].v<=x){
        ans=k;
        pre(t[k].r,x);
     }
     else pre(t[k].l,x);
}
void sub(int k,int x)
{
     if(!k) return ;
     if(t[k].v>=x){
        ans=k;
        sub(t[k].l,x);
     }
     else sub(t[k].r,x);
}
void insert1(int x)
{
     ans=0; pre(root,x);
     if(ans!=0)  mi=min(mi,abs(t[ans].v-x));
     ans=0; sub(root,x);
     if(ans!=0)  mi=min(mi,abs(t[ans].v-x));
     insert(root,x);
}
int main()
{
    char type[15];
    int x,y;
    memset(pr,-1,sizeof(pr));
    mi=0x7fffffff;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
      scanf("%d",&a[i]);
      insert1(a[i]);
      if(i>1) q1.push(abs(a[i]-a[i-1]));
    }
    
    for(int i=1;i<=m;i++){
       scanf("%s",type);
       if(type[0]=='I'){
          scanf("%d%d",&x,&y);
          add(x,y);
          insert1(y); 
       }
       if(type[0]=='M'&&type[4]=='G'){
          while(!q2.empty()&&q1.top()==q2.top()){q1.pop(); q2.pop();}
          printf("%d\n",q1.top());
       }
       if(type[0]=='M'&&type[4]=='S')
          printf("%d\n",mi);
    }
  //  while(1);
    return 0;
}



posted @ 2017-08-01 21:09  HunterxHunterl  阅读(211)  评论(0)    收藏  举报