bzoj1058 [ZJOI2007]报表统计

题目大意 :给定一个序列,有多次询问和修改,将新元素插在原数列位置的后面,询问相邻元素差值最小,和数列中两元素最小的差。

STL解法:用一个set去维护相邻两个数差的最小值,用一个堆去维护所有序列中最小的差

#include<bits/stdc++.h>
using namespace std;
#define inf 1000000000
#define maxn 500005
int ed[maxn],st[maxn];//记录序列中每个位置的第一个和最后一个元素 
int n,m;
multiset<int>a,b;
map<int,int>mp;
priority_queue< int,vector<int>,greater<int> > k;
inline int read()//加了快读才能在bzoj卡过去 
{
    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*10+ch-'0';ch=getchar();}
    return x*f;
}

void insert(int x){
    mp[x]++;
    if(mp[x]==1)a.insert(x);
} 
void push(int x){
    int l=*--b.lower_bound(x),r=*b.lower_bound(x);//求x的前驱和后继,比较最小值。 
    k.push(min(x-l,r-x));
    b.insert(x);
}
int main(){
    n=read();m=read();
    b.insert(inf);//不要忘记初始化 
    b.insert(-inf);
    int x;
    for(int i=1;i<=n;i++){
    x=read();
    ed[i]=st[i]=x;
    push(x);
    }
    for(int i=2;i<=n;i++){
        insert(abs(st[i]-st[i-1]));
    }
    char s[15];int q,y;
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        if(s[0]=='I'){
            q=read();y=read();
            if(q!=n){
                int t=abs(ed[q]-st[q+1]);
                mp[t]--;
                if(!mp[t])a.erase(t);
            }
            insert(abs(ed[q]-y));
            insert(abs(y-st[q+1]));
            ed[q]=y;push(ed[q]);
        }
        else if(s[4]=='S'){
            printf("%d\n",k.top() );
        }
        else printf("%d\n",*a.begin());
    }
    return 0;
}

 

posted @ 2017-09-28 14:45  Elfish?  阅读(...)  评论(... 编辑 收藏