Evanyou Blog 彩带

P1110 [ZJOI2007]报表统计

题目描述

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_GAP22,MIN_SORT_GAP22。

再执行操作INSERT 2 6将得到:5, 3, 9, 6, 1

注意这个时候原序列的第2个元素后面已经添加了一个9,此时添加的6应加在9的后面。这个时候MIN_GAP2MIN_SORT_GAP1

于是小Q写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

输入输出格式

输入格式:

 

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

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

接下来的M行每行一个操作,即INSERT i kMIN_GAPMIN_SORT_GAP 中的一种(无多余空格或者空行)。

 

输出格式:

 

对于每一个MIN_GAPMIN_SORT_GAP命令,输出一行答案即可。

 

输入输出样例

输入样例#1: 
3 5
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP
输出样例#1: 
2
2
1

说明

对于30%的数据,N ≤ 1000 ,M ≤ 5000
对于100%的数据,N ,M ≤500000
对于所有的数据,序列内的整数不超过5×108

时限2s

 

Solution:

  本题splay+堆(好水啊,乱打的代码都能AC~)。

  分析题目:

    操作1,加入一个数,只会改变相邻的关系,所以数组模拟随便乱搞维护下相邻关系。

    操作2,加入一个数,改变的是两对相邻的差值,所以可以直接用带修改的堆去维护(pbds大法好!)。

    操作3,由于是维护全局最小值,那么只需要在加入数时,在其插入二叉搜索树的遍历过程中,与访问过的节点更新下答案,当然为了保证树的平衡,选用平衡树写写就行了。

代码:

/*Code by 520 -- 9.17*/
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/priority_queue.hpp>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
#define son(x) (x==ch[fa[x]][1])
using namespace std;
using namespace __gnu_pbds;
const int N=1000005;
int n,m,a[N<<1][2],tot,val[N<<1];
int root,ch[N][2],fa[N],cnt,date[N];
int minn=0x7fffffff;
struct node{
    int ls,rs,val;
    bool operator < (const node &a) const {return val>a.val;}
};
typedef __gnu_pbds::priority_queue<node,less<node>,pairing_heap_tag> heap;
heap q;
heap::point_iterator id[N];

int gi(){
    int a=0;char x=getchar();bool f=0;
    while((x<'0'||x>'9')&&x!='-') x=getchar();
    if(x=='-') x=getchar(),f=1;
    while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
    return f?-a:a;
}

il void rotate(int x){
    int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
    z?ch[z][c]=x:root=x; fa[x]=z;
    if(a) fa[a]=y; ch[y][b]=a;
    ch[x][!b]=y,fa[y]=x;
}

il void splay(int x,int i){
    while(fa[x]!=i){
        RE int y=fa[x],z=fa[y];
        if(z==i) rotate(x);
        else {
            if(son(x)==son(y)) rotate(y),rotate(x);
            else rotate(x),rotate(x);
        }
    }
}

void insert(int &rt,int x){
    if(!rt) {rt=++cnt,date[cnt]=x;return;}
    if(date[rt]==x) {minn=0;return;}
    if(x<date[rt])
        insert(ch[rt][0],x),fa[ch[rt][0]]=rt,minn=min(minn,abs(date[rt]-x));
    else 
        insert(ch[rt][1],x),fa[ch[rt][1]]=rt,minn=min(minn,abs(date[rt]-x));    
}

int main(){
    int pos,x; char s[10];
    n=gi(),m=gi(),tot=n;
    For(i,1,n) {
        val[i]=gi(),insert(root,val[i]),splay(cnt,0);
        if(i!=1) a[i][0]=i;
        if(i!=n) a[i][1]=i;
    }
    For(i,2,n) id[i]=q.push(node{i,i+1,abs(val[i]-val[i-1])});
    while(m--){
        scanf("%s",s);
        if(s[0]=='I') {
            pos=gi(),val[++tot]=gi(),insert(root,val[tot]),splay(cnt,0);
            int tp=a[pos][1];
            id[tot]=q.push(node{tot,tp,abs(val[tp]-val[tot])});
            if(pos!=n) q.modify(id[pos+1],node{pos+1,tot,abs(val[pos+1]-val[tot])});
            a[pos+1][0]=tot,a[pos][1]=tot;
        }
        else if(strlen(s)==7) printf("%d\n",q.top().val);
        else printf("%d\n",minn);
    }
    return 0;
}

 

posted @ 2018-09-17 22:57  five20  阅读(340)  评论(0编辑  收藏  举报
Live2D