zjwz • 9个月前
using namespace std;
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;
}
评论:
请先登录,才能进行评论