bzoj 1058: [ZJOI2007]报表统计

Description

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

solution

正解:堆+平衡树
又堕落了QwQ,说好的平衡树呢?
对于第一个操作,我们链表维护一下即可
对于第二个询问,我们维护一个堆,我们每加入一个元素就把与前后差值加入堆中,堆中记录后继,便于删除.
对于第三个询问,答案单调不升,直接平衡树维护全局变量,插入时取min即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
#include <set>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=1000005,inf=2e9;
int n,m,nxt[N],cnt=0,pre[N],val[N],last[N],b[N];
char S[41];
struct node{
	int x,y,val;
	bool operator <(const node &pr)const{return val>pr.val;}
};
priority_queue<node>q;
multiset<int>G;
multiset<int>::iter it;
void work()
{
	int x,y,z,ans=inf;node k;
	scanf("%d%d",&n,&m);cnt=n;
	for(int i=1;i<=n;i++){
		scanf("%d",&val[i]);b[i]=val[i];
		last[i]=i;pre[i]=i-1;nxt[i]=i+1;
		if(i!=1)q.push((node){i-1,i,abs(val[i]-val[i-1])});
		G.insert(val[i]);
	}
	sort(b+1,b+n+1);
	for(int i=2;i<=n;i++)ans=min(ans,b[i]-b[i-1]);
	G.insert(-inf);G.insert(inf);
	while(m--){
		scanf("%s",S);
		if(S[0]=='I'){
			scanf("%d%d",&x,&z);
			y=last[x];
			cnt++;val[cnt]=z;
			if(x<n)pre[x+1]=cnt,nxt[cnt]=x+1;
			last[x]=cnt;nxt[y]=cnt;pre[cnt]=y;

			q.push((node){y,cnt,abs(val[y]-z)});
			if(x<n)q.push((node){cnt,x+1,abs(val[x+1]-z)});

			it=G.lower_bound(z);
			if(*it!=-inf){
				ans=min(ans,abs(*it-z));
				--it;
				if(*it!=-inf)ans=min(ans,abs(*it-z));
			}
			it=G.upper_bound(z);
			if(*it!=inf)ans=min(ans,abs(*it-z));
			G.insert(z);
		}
		else if(S[4]=='G'){
			while(!q.empty()){
				k=q.top();
				if(nxt[k.x]!=k.y)q.pop();
				else {printf("%d\n",k.val);break;}
			}
		}
		else printf("%d\n",ans);
	}
}

int main()
{
	freopen("pp.in","r",stdin);
	freopen("pp.out","w",stdout);
	work();
	return 0;
}

posted @ 2017-12-14 22:51  PIPIBoss  阅读(101)  评论(0编辑  收藏  举报