[ZJOI2007]报表统计 解题报告

11 篇文章 0 订阅
10 篇文章 0 订阅

[ZJOI2007]报表统计

Time Limit: 15 Sec   Memory Limit: 162 MB

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

Input

第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。第二行为N个整数,为初始序列。接下来的M行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无多余空格或者空行)。

Output

对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。

Sample Input

3 5
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP

Sample Output

2
2
1

HINT

对于100%的数据,N , M ≤500000 对于所有的数据,序列内的整数不超过5*10^8。

这道题又写了我一上午。。思路一开始不是很清晰,需要记录N个表头表尾,但是一开始我忘了维护表头,又忘了记录表尾。。编了一个数据结果弱得不得了根本没测出错来,导致第一遍交全WA了。

还有TLE。。原来Set.end()是遍历一遍Set容器。。如果要判是否有前驱后继的话还应该需要手动加一个MAXN和-MAXN.
下道题一定要注意啦:
①写题的时候思路一定要清晰,知道自己要做什么,这句话是什么意思。
②写完以后先大体读一遍,走一遍程序的流程;多编数据,至少两个,尽量卡飞自己的程序。
③以后再也不要用.end()啦!!还是手动插入一个MAXN吧。
④Code Trick:优先队列+布尔数组≈堆+映射;以后一定都学会用!
Splay+手写堆:
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
char * ptr=(char *)malloc(20000000);
inline void in(int &x){
	bool flag=0;
	while(*ptr<'0'||*ptr>'9')
		if(*ptr++=='-')
			flag=1;
	x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
	if(flag)x=-x;
}

struct HS{
	int key,x;
	inline bool operator < (const HS a) const{
		return key<a.key;
	}
}heap[1000001];
int point[500001],heapsize,a[500001],A[500001];
inline void up(int now){
	for(int next=now>>1;next&&heap[now]<heap[next];now=next,next>>=1){
		point[heap[now].x]=next;
		point[heap[next].x]=now;
		swap(heap[now],heap[next]);
	}
}
inline void down(int now){
	int next=now<<1;
	while(next<heapsize){
		if(next+1<heapsize&&heap[next+1]<heap[next])++next;
		if(heap[now]<heap[next])return;
		point[heap[now].x]=next;
		point[heap[next].x]=now;
		swap(heap[now],heap[next]);
		now=next,next<<=1;
	}
}
#include<set>
struct SS{
	SS * f,* c[2];
	int key;
	bool it;
}* nil=new SS((SS){nil,nil,nil,0,0}),* root;
inline void zig(SS * x,bool d){
	SS * ftr=x->f;
	if(ftr->it)ftr->it=0,x->it=1;
	x->f=ftr->f;
	if(x->f->c[0]==ftr)x->f->c[0]=x;
	else x->f->c[1]=x;
	ftr->c[d]=x->c[!d],ftr->c[d]->f=ftr;
	x->c[!d]=ftr,ftr->f=x;
}
inline void splay(SS * x){
	for(bool d;!x->it;zig(x,d)){
		d=x->f->c[1]==x;
		if(!x->f->it&&d==(x->f->f->c[1]==x->f))zig(x->f,d);
	}
	root=x;
}
inline bool insert(int A){
	SS * x=root;
	while(1){
		if(A==x->key)return 1;
		if(A<x->key)
			if(x->c[0]==nil){
				x->c[0]=new SS((SS){x,nil,nil,A,0});
				x=x->c[0];
				break;
			}
			else x=x->c[0];
		else
			if(A>x->key)
				if(x->c[1]==nil){
					x->c[1]=new SS((SS){x,nil,nil,A,0});
					x=x->c[1];
					break;
				}
			else x=x->c[1];
	}
	splay(x);
	return 0;
}
bool flag=1;
int ans=0x7fffffff;
inline void I(int A){
	if(insert(A)){
		flag=0;
		ans=0;
		return;
	}
	SS * x;
	if(root->c[1]!=nil){
		x=root->c[1];
		while(x->c[0]!=nil)x=x->c[0];
		ans=min(ans,x->key-A);
	}
	if(root->c[0]!=nil){
		x=root->c[0];
		while(x->c[1]!=nil)x=x->c[1];
		ans=min(ans,A-x->key);
	}
}
int main(){
	freopen("form.in","r",stdin);
	freopen("form.out","w",stdout);
	fread(ptr,1,20000000,stdin);
	int N,M,i,tot=0;
	in(N),in(M),in(a[1]);
	root=new SS((SS){nil,nil,nil,a[1],1});
	heapsize=N;
	SS * x;
	for(i=1;i<N;++i){
		point[i]=i;
		in(a[i+1]);
		heap[i]=(HS){abs(a[i]-a[i+1]),i};
		if(flag)I(a[i+1]);
	}
	memcpy(A,a,sizeof(a));
	for(i=N;--i;)down(i);
	int k;/*
	for(i=1;i<heapsize;++i)cout<<i<<":"<<heap[i].key<<" "<<heap[i].x<<"\n";
	cout<<"XXXXXXX\n";
	for(i=1;i<N;++i)cout<<i<<":"<<point[i]<<endl;*/
	while(M--){
		//cout<<"------"<<M<<"------\n";
		while(*ptr!='I'&&*ptr!='M')++ptr;
		for(i=0;i<4;++i)++ptr;
		switch(*ptr){
			case 'R':
				in(i),in(k);
				if(i!=N){
					//if(tot>=100&&tot<=110)cout<<"A:("<<i<<")"<<a[i]<<"->"<<k<<"->"<<A[i+1]<<endl;
					heap[point[i]]=(HS){abs(a[i]-k),N};
					point[N]=point[i];
					up(point[N]);
					down(point[N]);
					heap[point[N]].x=0;
					/*
					for(i=1;i<heapsize;++i)cout<<i<<":"<<heap[i].key<<" "<<heap[i].x<<"\n";
					cout<<"XXXXXXX\n";
					for(i=1;i<N;++i)cout<<i<<":"<<point[i]<<endl;*/
					
					//cout<<"A:"<<abs(a[i+1]-k)<<endl;
					heap[heapsize]=(HS){abs(A[i+1]-k),i};
					point[i]=heapsize;
					up(heapsize++);
				}
				else{
					heap[heapsize]=(HS){abs(a[i]-k),0};
					up(heapsize++);
				}
				if(flag)I(k);
				a[i]=k;
				break;
			case 'G':++tot;printf("%d\n",heap[1].key);break;
			case 'S':++tot;printf("%d\n",ans);
		}/*
		if(tot>=100&&tot<=110){
			cout<<"-------"<<M<<"------\n";
			cout<<heap[1].key<<" "<<ans<<":\n";
			for(i=1;i<heapsize;++i)cout<<i<<":"<<heap[i].key<<" "<<heap[i].x<<"\n";
			cout<<"XXXXXXX\n";
			for(i=1;i<N;++i)cout<<i<<":"<<point[i]<<endl;
			cout<<endl;
		}*/
	}
}
Set+priority_heap:
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
char * ptr=(char *)malloc(20000000);
inline void in(int &x){
	bool flag=0;
	while(*ptr<'0'||*ptr>'9')
		if(*ptr++=='-')
			flag=1;
	x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
	if(flag)x=-x;
}
struct HS{
	int key,x;
	inline bool operator < (const HS a) const{
		return key>a.key;
	}
};
int point[500000],a[500001],A[500001];
bool p[1500001];
#include<queue>
priority_queue<HS> q;
#include<set>
#define MAXN 0x7fffffff
int main(){
	freopen("form.in","r",stdin);
	freopen("form.out","w",stdout);
	fread(ptr,1,20000000,stdin);
	int N,M,ans=MAXN,i,tot=0;
	in(N),in(M),in(a[1]);
	bool flag=1;
	set<int> Set;
	set<int>::iterator it;
	Set.insert(MAXN);
	Set.insert(a[1]);
	Set.insert(-MAXN);
	for(i=1;i<N;++i){
		in(a[i+1]);
		point[i]=tot;
		q.push((HS){abs(a[i]-a[i+1]),tot++});
		if(flag){
			it=Set.lower_bound(a[i+1]);
			if(*it!=MAXN)ans=min(ans,*it-a[i+1]);
			if(*--it!=-MAXN)ans=min(ans,a[i+1]-*it);
			if(ans==0)flag=0;
			else Set.insert(a[i+1]);
		}
	}
	memcpy(A,a,sizeof(a));
	int k;
	while(M--){
		//cout<<"------"<<M<<"------\n";
		while(*ptr!='I'&&*ptr!='M')++ptr;
		for(i=0;i<4;++i)++ptr;
		switch(*ptr){
			case 'R':
				in(i),in(k);
				if(i!=N){
					q.push((HS){abs(a[i]-k),tot++});
					q.push((HS){abs(A[i+1]-k),tot});
					p[point[i]]=1;
					point[i]=tot++;
				}
				else q.push((HS){abs(a[i]-k),tot++});
				if(flag){
					it=Set.lower_bound(k);
					if(*it!=MAXN)ans=min(ans,*it-k);
					if(*--it!=-MAXN)ans=min(ans,k-*it);
					if(ans==0)flag=0;
					else Set.insert(k);
				}
				a[i]=k;
				break;
			case 'G':
				while(p[q.top().x])q.pop();
				printf("%d\n",q.top().key);
				break;
			case 'S':printf("%d\n",ans);
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值