[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 k
,MIN_GAP
,MIN_SORT_GAP
中的一种(无多余空格或者空行)。
输出格式
对于每一个 MIN_GAP
和 MIN_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;
}