[BZOJ 1058] [ZJOI2007] 报表统计 【平衡树】

题目链接:BZOJ - 1058

 

题目分析

这道题看似是需要在序列中插入一些数字,但其实询问的内容只与相邻的元素有关。

那么我们只要对每个位置维护两个数 Ai, Bi, Ai 就是初始序列中 i 这个位置的数, Bi 是在 i 这个位置insert的最后一个数。

那么在 i insert一个数 Num 的时候,造成的影响就是使得 Bi 和 A(i+1) 不再相邻,同时使 Bi 与 Num, Num 与 A(i+1) 相邻。然后将 Bi 更新为 Num。

这样就只需要实现一个multiset的功能就可以了。可以手写平衡树,也可以使用STL,当然STL会慢许多。 

 

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

const int MaxN = 500000 + 5, INF = 1000000015, MaxL = 25;

int n, m, MSG;
int A[MaxN], B[MaxN];

char Str[MaxL];

 
multiset<int> S, S2;
multiset<int>::iterator It, It2;

inline int gmax(int a, int b) {return a > b ? a : b;}
inline int gmin(int a, int b) {return a < b ? a : b;}
inline int Abs(int a) {return a < 0 ? -a : a;}

void Before(int x) 
{
	It = S.lower_bound(x);
	if (It == S.end()) 
	{
		It--;
		MSG = gmin(MSG, x - *It);
		return;
	}
	if (*It == x) 
	{
		MSG = 0;
		return;
	}
	if (It == S.begin()) return;
	It--;
	MSG = gmin(MSG, x - *It);
}

void After(int x) 
{
	It = S.upper_bound(x);
	if (It == S.end()) return;
	MSG = gmin(MSG, *It - x);
}

int main()
{
	scanf("%d%d", &n, &m);
	S.clear(); S2.clear();
	for (int i = 1; i <= n; ++i) 
	{
		scanf("%d", &A[i]);
		B[i] = A[i];
		S.insert(A[i]);
	}
	for (int i = 2; i <= n; ++i) 
		S2.insert(Abs(A[i] - A[i - 1]));
	MSG = INF;
	for (int i = 1; i <= n; ++i) 
	{
		S.erase(S.find(A[i]));
		Before(A[i]);
		After(A[i]);
		S.insert(A[i]);
	}
	int Pos, Num;
	for (int i = 1; i <= m; ++i) 
	{
		scanf("%s", Str + 1);
		if (Str[1] == 'I') 
		{
			scanf("%d%d", &Pos, &Num);
			Before(Num);
			After(Num);
			S.insert(Num);
			if (Pos == n) 
			{
				B[Pos] = Num;
				continue;
			}
			S2.erase(S2.find(Abs(A[Pos + 1] - B[Pos])));
			S2.insert(Abs(Num - B[Pos]));
			S2.insert(Abs(A[Pos + 1] - Num));
			B[Pos] = Num;
		}
		else if (Str[5] == 'G') 
		{
			It2 = S2.begin();
			printf("%d\n", *It2);
		}
		else 
		{
			printf("%d\n", MSG);
		}
	}
	return 0;
}

  

posted @ 2015-03-08 09:24  JoeFan  阅读(491)  评论(0编辑  收藏  举报