1

zjwz  •  9个月前


define _CRT_SECURE_NO_WARNINGS

include

include

include

using namespace std;

define ll long long

define lson l,m,rt<<1

define rson m+1,r,rt<<1|1

const int INF = 0x3f3f3f3f; const int N = 100005;

int num[N];

struct A {//需要存储opt和x,故写成结构体

int opt, x;

} q[N];//q[N]存原始数据

int tree[N << 2];//线段树

void push_up(int rt) {//更新节点的值

//等价于tree[rt] = tree[rt *2] + tree[rt *2+1];
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];

}

//在[l,r]区间插入(c=1)或删除(c=-1)p void update(int p, int c, int l, int r, int rt) {

if (l == r) {//找到更新的位置
	tree[rt] += c;
	return;
}
int m = (l + r) >> 1;//更新mid
if (p <= m)//p小于等于mid,表示要修改的位置在左边
	update(p, c, lson);//递归左半部分
else//否则递归右半部分
	update(p, c, rson);
push_up(rt);//左右子树递归完后,依次更新根节点的值

}

//区间[L,R]的和 int query1(int L, int R, int l, int r, int rt) { //区间求和

if (L <= l && R >= r) {//区间[L,R]完全包含在该节点所维护的区间
	return tree[rt];//直接返回根节点的值
}
int m = (l + r) >> 1;
int ans = 0;
if (L <= m)//要查询的左半区间与该节点维护的左区间有重合
	ans += query1(L, R, lson);//递归查询做半区间
if (R > m)
	ans += query1(L, R, rson);
return ans;

}

int query2(int k, int l, int r, int rt) { //查询排名为k的数

if (l == r) {
	return l;
}
int m = (l + r) >> 1;
if (k <= tree[rt << 1])//要查的排名比左子树个数小,说明该数位于左子树
	return query2(k, lson);
else//否则位于右子树,第k名是右子树的k - tree[rt *2]名
	return query2(k - tree[rt << 1], rson);

}

int main() {

//freopen("10.in", "r", stdin);
//freopen("10.out", "w", stdout);
int m, k = 0;
scanf("%d", &m);//m组操作
for (int i = 0; i < m; i++) {
	scanf("%d%d", &q[i].opt, &q[i].x);
	if (q[i].opt != 4)//对很大的数进行离散化,查排名的数不用离散化
		num[k++] = q[i].x;
}
//离散化
sort(num, num + k);
int n = unique(num, num + k) - num;//对num数组去重

for (int i = 0; i < m; i++) {
	//对x离散化,num从0开始存,故最后要加1
	int x = lower_bound(num, num + n, q[i].x) - num + 1;
	if (q[i].opt == 1) { //插入
		update(x, 1, 1, n, 1);
	}
	if (q[i].opt == 2) { //删除
		update(x, -1, 1, n, 1);
	}
	if (q[i].opt == 3) { //查询x的排名
		if (x - 1 == 0)
			printf("1\n");
		else
			printf("%d\n", query1(1, x - 1, 1, n, 1) + 1);
	}
	if (q[i].opt == 4) { //查询排名为x的数
		//query2返回的是排名为x的数的下标(从1开始),输出为num中对应的值
		printf("%d\n", num[query2(q[i].x, 1, n, 1) - 1]);
	}
	if (q[i].opt == 5) { //求小于x的最大的数的值(前驱)
		//x的排名
		int rk = query1(1, x - 1, 1, n, 1) + 1;
		//query2返回x-1的下标,num从0开始,故-1
		printf("%d\n", num[query2(rk - 1, 1, n, 1) - 1]);
	}
	if (q[i].opt == 6) { //求大于x的最小的数的值(后继)
		int sum = query1(1, x, 1, n, 1);
		printf("%d\n", num[query2(sum + 1, 1, n, 1) - 1]);
	}
}
return 0;

}


评论:

请先登录,才能进行评论