您的位置:首页 > 其它

勤快的love 枫

2017-08-01 21:08 23 查看


题目描述

小绝恋love 枫是一个出纳,经常需要做一些统计报表的工作。今天是绝恋love 枫的生日,小绝恋love 枫希望可以帮爸爸分担一些工作,作为他的生日礼物之一。经过仔细观察,小绝恋love 枫发现统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。在最开始的时候,有一个长度为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。于是小绝恋love 枫写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

输入

第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。
第二行为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
,a
;
struct  treap
{
int l,r,w,v,rnd;
}t
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  treap