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; }