1058: [ZJOI2007]报表统计
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1791 Solved: 632
[ Submit][ Status]
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
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP
Sample Output
2
1
HINT
对于30%的数据,N ≤ 1000 , M ≤ 5000 对于100%的数据,N , M ≤500000 对于所有的数据,序列内的整数不超过5*108。
Source
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 500000 + 20;
int A[maxn];
bool vis[maxn];
int last[maxn];
set<int> S;
set<int>::iterator it;
map<int, int> cnt;
map<int, int>::iterator mit, tmit;
char str[20];
int main() {
int n, m;
int MIN_GAP, MIN_SORT_GAP = -1;
memset(vis, 0, sizeof(vis));
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) {
scanf("%d", &A[i]);
it = S.lower_bound(A[i]);
if(it != S.end()) {
int t = abs(A[i] - *it);
if(MIN_SORT_GAP == -1 || t < MIN_SORT_GAP) MIN_SORT_GAP = t;
}
if(it != S.begin()) {
it--;
int t = abs(A[i] - *it);
if(MIN_SORT_GAP == -1 || t < MIN_SORT_GAP) MIN_SORT_GAP = t;
}
S.insert(A[i]);
if(i > 1) {
int t = abs(A[i] - A[i-1]);
cnt[t]++;
if(i == 2) MIN_GAP = t;
else if(i > 2 && t< MIN_GAP) MIN_GAP = t;
}
}
for(int i=0; i<m; i++) {
scanf("%s", str);
if(strcmp(str, "MIN_GAP") == 0) {
printf("%d\n", MIN_GAP);
} else if(strcmp(str, "MIN_SORT_GAP") == 0) {
printf("%d\n", MIN_SORT_GAP);
} else if(strcmp(str, "INSERT") == 0) {
int pos, val;
scanf("%d%d", &pos, &val);
it = S.lower_bound(val);
if(it != S.end()) {
int t = abs(val - *it);
if(MIN_SORT_GAP == -1 || t < MIN_SORT_GAP) MIN_SORT_GAP = t;
}
if(it != S.begin()) {
it--;
int t = abs(val - *it);
if(MIN_SORT_GAP == -1 || t < MIN_SORT_GAP) MIN_SORT_GAP = t;
}
S.insert(val);
int tai = vis[pos] ? last[pos] : A[pos];
int t1 = abs(tai-val);
cnt[t1]++;
if(pos < n) {
int t2 = abs(val - A[pos+1]);
cnt[t2]++;
int t3 = abs(tai - A[pos+1]);
cnt[t3]--;
}
mit = cnt.begin();
while(mit != cnt.end() && mit->second == 0) {
tmit = mit++;
cnt.erase(tmit);
}
MIN_GAP = mit->first;
vis[pos] = 1;
last[pos] = val;
}
}
return 0;
}