ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu1110 报表统计

2022-07-26 17:04:43  阅读:159  来源: 互联网

标签:sz 报表 pt MIN luogu1110 pos GAP smn 统计


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

标签:sz,报表,pt,MIN,luogu1110,pos,GAP,smn,统计
来源: https://www.cnblogs.com/gryzy/p/16521643.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有