spoj ORDERSET - Order statistic set Hash+树状数组。附另一种解法,使用了policy based data structrue-CSDN博客

76 阅读2分钟

这个题本来是学树堆Treap练习的,但是我的板子超时,无奈之下去墙那边看了下,老外用了树状数组给解出来了,很巧妙的离散化操作。。。Orz。。。

ORDERSET - Order statistic set

#tree  #binary-search

\

EnglishVietnamese

In this problem, you have to maintain a dynamic set of numbers which support the two fundamental operations

  • INSERT(S,x): if x is not in S, insert x into S
  • DELETE(S,x): if x is in S, delete x from S

and the two type of queries

  • K-TH(S) : return the k-th smallest element of S
  • COUNT(S,x): return the number of elements of S smaller than x

Input

  • Line 1: Q (1 ≤ Q ≤ 200000), the number of operations
  • In the next Q lines, the first token of each line is a character I, D, K or C meaning that the corresponding operation is INSERT, DELETE, K-TH or COUNT, respectively, following by a whitespace and an integer which is the parameter for that operation.

If the parameter is a value x, it is guaranteed that 0 ≤ |x| ≤ 109. If the parameter is an index k, it is guaranteed that 1 ≤ k ≤ 109.

Output

For each query, print the corresponding result in a single line. In particular, for the queries K-TH, if k is larger than the number of elements in S, print the word 'invalid'.

Example

Input
8
I -1
I -1
I 2
C 0
K 2
D -1
K 1
K 2

Output
1
2
2
invalid
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 200005
#define pb push_back
int tree[200009], Hash[200009], save[200009];
inline int lowbit(int x) {
	return x & -x;
}
void update(int pos, int val) {
	for (int i = pos; i <= MAX; i += lowbit(i))
		tree[i] += val;
}
int sum(int pos) {
	int ans = 0;
	for (int i = pos; i > 0; i -= lowbit(i))
		ans += tree[i];
	return ans;
}
struct Data {
	int pos, val, Hash;
	char type;
};
Data d[200009], query[200009];
bool cmp(const Data &a, const Data &b) {
	return a.val == b.val ? a.pos < b.pos : a.val < b.val; //数据优先
}
int b_search(int k) {
	int low = 0, high = 200000, mid;
	while (low < high) {
		mid = (low + high) >> 1;
		if (sum(mid) >= k)
			high = mid;
		else
			low = mid + 1;
	}
	return low;
}
int main() {
	int q;
	scanf("%d", &q);
	for (int i = 0; i < q; i++) {
		scanf(" %c%d", &d[i].type, &d[i].val);
		d[i].pos = i + 1;
	}
	sort(d, d + q, cmp);
	int cnt = 1, prev = d[0].val;
	d[0].Hash = cnt;
	save[cnt] = d[0].val;
	for (int i = 1; i < q; i++)	{ //hash,不然不能用树状数组
		if (prev != d[i].val) {
			prev = d[i].val;
			cnt++;
			d[i].Hash = cnt;
			save[cnt] = d[i].val;
		}
		else
			d[i].Hash = cnt;
	}
	for (int i = 0; i < q; i++) {
		query[d[i].pos] = d[i];
	}
	cnt = 0;
	for (int i = 1; i <= q; i++) {
		if (query[i].type == 'I') {
			if (!Hash[query[i].Hash]) {
				cnt++;
				Hash[query[i].Hash] = 1;
				update(query[i].Hash, 1);
			}
		}
		else if (query[i].type == 'D') {
			if (Hash[query[i].Hash]) {
				cnt--;
				Hash[query[i].Hash] = 0;
				update(query[i].Hash, -1);
			}
		}
		else if (query[i].type == 'K') {
			if (query[i].val > cnt)
				printf("invalid\n");
			else
				printf("%d\n", save[b_search(query[i].val)]);
		}
		else
			printf("%d\n", sum(query[i].Hash - 1)); //查询小于query[i].hash的值
	}
	return 0;
}

\

他的另一种解法(这也太神了吧)。现在不是大部分OJ支持这种操作(拓展的pb_ds, codeforces spoj 支持)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
int main(){
    pbd_set s;
    int t;
    scanf("%d ",&t);
    while(t--){
        char typ;
        int n;
        scanf(" %c%d",&typ , &n);
        if(typ == 'I')
            s.insert(n);
        else if (typ == 'D')
            s.erase(n);
        else if (typ == 'K'){
            int ans;
            n--;
            if(s.find_by_order(n) != s.end()){
                ans = *s.find_by_order(n);
                printf("%d\n",ans);
            }
            else 
                printf("invalid\n");
        }
        else{
            int ans = s.order_of_key(n);
            printf("%d\n",ans);
        }
    }
    return 0;
}


\

\