当前位置: 代码迷 >> 综合 >> bzoj 3224 Tyvj 1728 普通平衡树
  详细解决方案

bzoj 3224 Tyvj 1728 普通平衡树

热度:35   发布时间:2024-01-24 14:11:04.0

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

 

1.n的数据范围:n<=100000

 

2.每个数的数据范围:[-2e9,2e9]

解题报告:

平衡数的模板题,但我使用了权值线段树来解决,方便之后学习主席树。

1:对于1,2操作。直接加减1,很好处理。 如果这里是删除所有相同的,直接找到叶子节点,然后赋值为0。(好像是这样=.=)

2:对于3操作。先通过离散化得到索引 idx。查询[1, idx-1]的值域。结果加1就是答案了。这里re了很多发,很懵逼=.=。当idx=1时可以直接返回1,不用查询,如果查询还会死循环。当然也看每个人写的查询函数。

3:对于4操作。每次和T[ls]的数值比较,小于等于一定在左子树,查询左子树。大于的话,一定在右子树,这时转化为求右子树的第k-T[ls]。

4:对于5操作。我使用的是xRank+Kth做的。当然有直接求的,这里就不赘述了。我们要查x的前驱,相当于先查[1, idx-1]的值域信息k。然后查询第k大的数就行了。

5:对于6操作。和上面的操作差不多。就不多说了。

代码:

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define push_up T[rt] = T[ls]+T[rs]
using namespace std;
typedef long long ll;
const ll N = 100000+10;
ll num[N], tool[N], T[N<<2], op[N];
ll Hash(ll n){//下标从1开始hashsort(tool+1, tool+1+n);ll len = unique(tool+1, tool+1+n)-tool-1;return len;
}
void update(ll rt, ll l, ll r, ll idx, ll val){if(l == r){T[rt] += val;return ;}ll mid = l+(r-l)/2;if(mid >= idx)update(ls, l, mid, idx, val);if(mid < idx)update(rs, mid+1, r, idx, val);push_up;
}
ll Kth(ll rt, ll l, ll r, ll k){if(l == r)return l;ll mid = l+(r-l)/2;if(T[ls] >= k)return Kth(ls, l, mid, k);if(T[ls] < k)return Kth(rs, mid+1, r, k-T[ls]);
}
ll xRank(ll rt, ll l, ll r, ll ql, ll qr){if(qr == 0)return 0;if(ql <= l && r <= qr)return T[rt];ll mid = l+(r-l)/2, ans = 0;if(mid >= ql)ans += xRank(ls, l, mid, ql, qr);if(mid < qr)ans += xRank(rs, mid+1, r, ql, qr);return ans;
}
ll pre(ll rt, ll l, ll r, ll val, ll len){ll idx = lower_bound(tool+1, tool+1+len, val)-tool;ll k = xRank(rt, l, r, 1, idx-1);return tool[Kth(rt, l, r, k)];
}
ll next(ll rt, ll l, ll r, ll val, ll len){ll idx = lower_bound(tool+1, tool+1+len, val)-tool;ll k = xRank(rt, l, r, 1, idx);return tool[Kth(rt, l, r, k+1)];
}
int main(){ll m, cnt = 0, idx;scanf("%lld", &m);for(ll i=1; i<=m; ++i){scanf("%lld%lld", op+i, num+i);if(op[i] != 4)tool[++cnt] = num[i];}ll len = Hash(cnt);for(ll i=1; i<=m; ++i){if(op[i] <= 3)idx = lower_bound(tool+1, tool+1+len, num[i])-tool;if(op[i] == 1)update(1, 1, len, idx, 1);if(op[i] == 2)update(1, 1, len, idx, -1);if(op[i] == 3)printf("%lld\n", xRank(1, 1, len, 1, idx-1)+1);if(op[i] == 4)printf("%lld\n", tool[Kth(1, 1, len, num[i])]);if(op[i] == 5)printf("%lld\n", pre(1, 1, len, num[i], len));if(op[i] == 6)printf("%lld\n", next(1, 1, len, num[i], len));}return 0;
}