luogu1110 报表统计

[ZJOI2007] 报表统计

题目描述

小 Q 的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小 Q 希望可以帮妈妈分担一些工作,作为她的生日礼物之一。

经过仔细观察,小 Q 发现统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。

在最开始的时候,有一个长度为 \(n\) 的整数序列 \(a\),并且有以下三种操作:

  • INSERT i k:在原数列的第 \(i\) 个元素后面添加一个新元素 \(k\);如果原数列的第 \(i\) 个元素已经添加了若干元素,则添加在这些元素的最后(见样例说明)。
  • MIN_GAP:查询相邻两个元素的之间差值(绝对值)的最小值。
  • MIN_SORT_GAP:查询所有元素中最接近的两个元素的差值(绝对值)。

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

输入格式

第一行包含两个整数,分别表示原数列的长度 \(n\) 以及操作的次数 \(m\)

第二行为 \(n\) 个整数,为初始序列,第 \(i\) 个整数表示 \(a_i\)

接下来的 \(m\) 行,每行一个操作,即INSERT i kMIN_GAPMIN_SORT_GAP 中的一种(无多余空格或者空行)。

输出格式

对于每一个 MIN_GAPMIN_SORT_GAP 命令,输出一行答案即可。

样例 #1

样例输入 #1

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

样例输出 #1

2
2
1

提示

样例输入输出 1 解释

一开始的序列为 \(\{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\)


数据规模与约定

对于全部的测试点,保证 \(2 \le n, m \le 5\times10^5\)\(1 \leq i \leq n\)\(0 \leq a_i, k \leq 5 \times 10^8\)


首先,题目要细读。题意是在n个位置放上n个数,后面会在某个位置再在后面加数。这时就相当于把多个数分为n段,段所段之间是有序的,段内各个数之间也是有序的。
两种询问,一种是不管分段和次序,所有的数的最小跨度。另一种是相临两个数之间的最小跨度。
第一种跨度明显用平衡树维护,每次求前驱和后继,这样就有了最小跨度。
第二种用可删除堆,也就是两个堆,来维护。
平衡树太难写了,于是就写了一个multiset。学了不少东西。


#include<bits/stdc++.h>
using namespace std;
const int maxn=5e6+10;
multiset<int>t;//维护排序最小值 
struct Heap
{
	priority_queue< int,vector <int> , greater<int> >qr,qc;
	void insert(int x)
	{
		qr.push(x);
	}
	void del(int x)
	{
		qc.push(x);
	}
	int get()
	{
		while(!qc.empty()&&!qr.empty()&&qr.top()==qc.top())qr.pop(),qc.pop();
		return qr.top();
	}
}heap;//维护相邻最小值 
int n,m;
char s[20];
int sz[maxn][2];
int mn=0x7fffffff,smn=0x7fffffff;
typedef multiset<int>::iterator it;
int abs(int x){return x<0?-x:x;}
it tp;
void print()
{
	cout<<"********************"<<endl;
	for(it x=t.begin();x!=t.end();++x)cout<<*x<<endl;
	cout<<"********************"<<endl;
}
int main()
{
	scanf("%d%d",&n,&m);
	memset(sz,-1,sizeof sz);
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&sz[i][0]);
		if(i!=1)heap.insert(abs(sz[i][0]-sz[i-1][0]));
		if(smn)
		{
			pair<it,it> pt=t.equal_range(sz[i][0]);
			if(pt.first != pt.second){smn=0;continue;}
			if(pt.second !=t.end())smn=min(smn,abs(*pt.second-sz[i][0]));
			if(pt.first !=t.begin())tp=pt.first,tp--,smn=min(smn,abs(sz[i][0]-*(tp)));
			t.insert(sz[i][0]);
		}
	}
	while(m--)
	{
		scanf("%s",s);
		if(s[4]=='S')printf("%d\n",smn);
		else if (s[4]=='G')printf("%d\n",heap.get());
		else
		{
			int pos,val;
			scanf("%d%d",&pos,&val);
			if(sz[pos][1]==-1)heap.insert(abs(sz[pos][0]-val));
			else heap.insert(abs(sz[pos][1]-val));
			if(pos!=n)heap.insert(abs(sz[pos+1][0]-val)),heap.del(abs(sz[pos+1][0]-sz[pos][sz[pos][1]==-1?0:1]));
			sz[pos][1]=val;
			if(smn)
			{
				pair<it,it> pt=t.equal_range(val);
				if(pt.first != pt.second){smn=0;continue;}
				if(pt.second !=t.end())smn=min(smn,abs(*pt.second-val));
				if(pt.first!=t.begin())tp=pt.first,tp--,smn=min(smn,abs(val-*(tp)));
				t.insert(val);
			}
		}
	}
	return 0;
}

posted on 2022-07-26 16:49  gryzy  阅读(44)  评论(0编辑  收藏  举报

导航