链接:https://www.nowcoder.com/acm/contest/93/L
来源:牛客网
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
你们wyh学长小时候住在河边,因为周围的生态环境非常好,所以经常会有天鹅浮在湖面上,每只天鹅都长得不一样,它们偶尔排成一排,偶尔分散开,偶尔也会去其他河畔,wyh学长为了统计它们的个数,编了一个程序赋予它们一个“萌”值,但是这些天鹅很不听话,一会儿会从别的地方游过来一两只,一会儿又会在统计过程中游走一两只,现在请你帮他完成统计任务。
输入描述:
共有T(T<=10)组数据,每组数据第一行为两个数 N, M (N,M <= 500000),代表有N只天鹅和M次操作,接下来一行是N个数字,下面M行首先会输入一个字符串S,接着会有三类操作,如果S是“insert”,接着输入一个正整数a,代表插入一只“萌”值为a的天鹅,如果S是“delete”,接着输入一个正整数a,代表删除一只“萌”值为a的天鹅,如果S是“query”,接着输入一个正整数k,代表查询“萌”值第k大的天鹅。
萌值为[1,1000000000],并且保证一定存在第k大
输出描述:
对应每次询问,输出询问结果。
示例1
输入
1
5 4
6 4 2 9 1
query 2
insert 7
delete 6
query 2
输出
6
7
分析:因为询问的区间只有一个,所以不需要主席树也可以解决。
因为所有的数字种类不会超过1e6,所以可以用离散化来映射。
双lglg版本:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long int
#define INF 0x3f3f3f3f
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn = 1e6 + 10;
int Sum[maxn << 2];
int Add[maxn << 2];
int A[maxn], n;
int B[maxn];
int C[maxn];
struct node {
int q, x;
}a[maxn];
void pushup(int rt) {
Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1];
}
void build(int l, int r, int rt) {
if (l == r) { Sum[rt] = 0; return; }
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int L, int C, int l, int r, int rt) {//A[L]+=C;
if (l == r) {
Sum[rt] += C; return;
}
int m = (l + r) >> 1;
if (L <= m) update(L, C, l, m, rt << 1);
else update(L, C, m + 1, r, rt << 1 | 1);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return Sum[rt];
}
int m = (l + r) >> 1;
int ans = 0;
if (L <= m) ans += query(L, R, l, m, rt << 1);
if (R > m) ans += query(L, R, m + 1, r, rt << 1 | 1);
return ans;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
char s[20]; int j = n;
for (int i = 1; i <= n; i++) {
scanf("%d", &A[i]); C[i] = A[i];
}
for (int i = 1; i <= m; i++) {
scanf("%s", s); scanf("%d", &a[i].x);
if (s[0] == 'q') {
a[i].q = 0;
}
else if (s[0] == 'i') {
a[i].q = 1;
A[++j] = a[i].x;
}
else if (s[0] == 'd') {
a[i].q = 2;
}
}
sort(A + 1, A + 1 + j); sort(C + 1, C + 1 + n);
memset(B, 0, sizeof B); A[0] = INF; int sz = 0;
for (int i = 1; i <= j; i++) {
if (A[i] != A[i - 1]) B[++sz] = A[i];
}
/* for (int i = 1; i <= sz; i++) {
cout << B[i] << " ";
}
cout << endl;
*/
memset(A, 0, sizeof A);
build(1, sz, 1);
for (int i = 1; i <= n; i++) {
int d = lower_bound(B + 1, B + sz + 1, C[i]) - B;
//cout << C[i] << " !!! " << d << endl;
update(d, 1, 1, sz, 1);
}
for (int i = 1; i <= m; i++)
{
if (a[i].q == 0) {
//int d=lower_bound(1,sz,a[i].x)
int l = 1, r = sz; int mid;
int ans;
while (l <= r) {
mid = (l + r) >> 1;
if (query(mid, sz, 1, sz, 1) >= a[i].x) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
printf("%d\n", B[ans]);
}
else if (a[i].q == 1) {
int d = lower_bound(B + 1, B + sz + 1, a[i].x) - B;
update(d, 1, 1, sz, 1);
}
else if (a[i].q == 2) {
int d = lower_bound(B + 1, B + sz + 1, a[i].x) - B;
update(d, -1, 1, sz, 1);
}
}
}
return 0;
}
单lg版本:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long int
#define INF 0x3f3f3f3f
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn = 1e6 + 10;
int Sum[maxn << 2];
int Add[maxn << 2];
int A[maxn], n;
int B[maxn];
int C[maxn];
struct node {
int q, x;
}a[maxn];
void pushup(int rt) {
Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1];
}
void build(int l, int r, int rt) {
if (l == r) { Sum[rt] = 0; return; }
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int L, int C, int l, int r, int rt) {//A[L]+=C;
if (l == r) {
Sum[rt] += C; return;
}
int m = (l + r) >> 1;
if (L <= m) update(L, C, l, m, rt << 1);
else update(L, C, m + 1, r, rt << 1 | 1);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return Sum[rt];
}
int m = (l + r) >> 1;
int ans = 0;
if (L <= m) ans += query(L, R, l, m, rt << 1);
if (R > m) ans += query(L, R, m + 1, r, rt << 1 | 1);
return ans;
}
int Q(int l, int r, int rt, int x) {
// (x <= 0) return rt;
if (l == r) return l;
int mid = (l + r) >> 1;
if (Sum[rt << 1 | 1] >= x)
return Q(mid+1, r, rt << 1 | 1, x);
else
return Q(l, mid, rt << 1, x - Sum[rt << 1 | 1]);
}
int main()
{
//cout << (5 << 1 | 1) << endl;
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
char s[20]; int j = n;
for (int i = 1; i <= n; i++) {
scanf("%d", &A[i]); C[i] = A[i];
}
for (int i = 1; i <= m; i++) {
scanf("%s", s); scanf("%d", &a[i].x);
if (s[0] == 'q') {
a[i].q = 0;
}
else if (s[0] == 'i') {
a[i].q = 1;
A[++j] = a[i].x;
}
else if (s[0] == 'd') {
a[i].q = 2;
}
}
sort(A + 1, A + 1 + j); sort(C + 1, C + 1 + n);
memset(B, 0, sizeof B); A[0] = INF; int sz = 0;
for (int i = 1; i <= j; i++) {
if (A[i] != A[i - 1]) B[++sz] = A[i];
}
/* for (int i = 1; i <= sz; i++) {
cout << B[i] << " ";
}
cout << endl;
*/
memset(A, 0, sizeof A);
build(1, sz, 1);
for (int i = 1; i <= n; i++) {
int d = lower_bound(B + 1, B + sz + 1, C[i]) - B;
//cout << C[i] << " !!! " << d << endl;
update(d, 1, 1, sz, 1);
}
for (int i = 1; i <= m; i++)
{
if (a[i].q == 0) {
int ans = Q(1, sz, 1, a[i].x);
printf("%d\n", B[ans]);
}
else if (a[i].q == 1) {
int d = lower_bound(B + 1, B + sz + 1, a[i].x) - B;
update(d, 1, 1, sz, 1);
}
else if (a[i].q == 2) {
int d = lower_bound(B + 1, B + sz + 1, a[i].x) - B;
update(d, -1, 1, sz, 1);
}
}
}
return 0;
}
主席树版本: