BZOJ1058 [ZJOI2007]报表统计 STL

给定一个数列 需要实现三种操作:

①在某个数后面加入一个数,如果曾经加入过则加在之前加的数之后

②查询所有相邻两个数的差的最小值

③查询全局差的最小值

用一个set和一个map维护相邻两数的差值

每次插入就删除原来的差值,再插入新的差值

因为全局差值只降不增

所以再开一个set存出现过的数,每次二分查找后更新差值再插入

因为BZOJ评测不分点所以卡过了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<map>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=500005,INF=1e9+1024;
inline void read(int &x)
{
    x=0;int 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();}
    x*=f;
}
map<int,int> md;
set<int> s0,sd;
int n,m,be[N],en[N],msg=INF;
inline void push(int x)
{
    int l=*--s0.lower_bound(x),r=*s0.lower_bound(x);
    msg=min(msg,min(x-l,r-x));
    s0.insert(x);
}
int main()
{
    read(n);read(m);
    s0.insert(INF);s0.insert(-INF);
    for(int i=1,a;i<=n;i++)
    {
        read(a);
        be[i]=en[i]=a;
        push(a);
    }
    for(int i=2;i<=n;i++)
    {
        int t=abs(be[i]-be[i-1]);
        sd.insert(t);md[t]++;
    }
    set<int>::iterator it;
     
    char op[13];
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='I'){
            int p,x,mx;
            read(p);read(x);
            if(p!=n)
            {
                mx=abs(en[p]-be[p+1]);
                if(!--md[mx])sd.erase(mx);
                //md[mx]--;
                 
            }
            mx=abs(x-en[p]);sd.insert(mx);md[mx]++;
            mx=abs(x-be[p+1]);sd.insert(mx);md[mx]++;
            en[p]=x;
            push(x);
        }
        else if(op[4]=='G'){
            it=sd.begin();
            printf("%d\n",*it);
        }
        else{
            printf("%d\n",msg);
        }
    }
    return 0;
}

开O2没用(逃)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值