BZOJ 1058 - [ZJOI2007]报表统计 STL splay [挖坑待填]

1058: [ZJOI2007]报表统计

Time Limit: 15 Sec   Memory Limit: 162 MB
Submit: 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

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

Sample Output

2
2
1

HINT

对于30%的数据,N ≤ 1000 , M ≤ 5000 对于100%的数据,N , M ≤500000 对于所有的数据,序列内的整数不超过5*108。

Source


[ Submit][ Status]




先用STL水过去的 先挖个坑 学了splay补上

对于MIN_SORT_GAP可以用set保存然后找出相邻两个求最小值然后更新
对于MIN_GAP,最开始想简单了,只考虑了插入一个数会增加两个差值,忘了考虑之前的一个差值应该去掉,所以WA了。
然后想法是把之前的所有差值和对应的相邻两个元素保存起来,但是感觉这有代码量太大,然后参考别人的,感觉自己好笨,为什么要保存相邻的两个元素?为了去掉的时候能找到啊。直接保存每个差值有多少个,然后去掉的时候相应的差值减1不就行了?。。。map保存差值的数量



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










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值