如果要看权值线段树是啥的萌新绕路,为你们节省时间,文章仅对代码进行解释.
main函数内对point数组有序,pos函数是二分查出值对应的离散化后的值(排名)。以此来对所有数都离散化处理,为存起来询问的离线做法。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod1 = 1e9 +7;
const int mod2 = 998244353;
const int mod3 = 1e9;
const double PI = acos(-1);
const double eps =1e-8;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned uint;
const int sq5=616991993;
#define ms(x, n) memset(x,n,sizeof(x))
#define debug printf("***debug***\n")
#define pii pair<int ,int>
#define X first
#define Y second
#define pb push_back
#define ls(i) i<<2
#define rs(i) i<<2|1
const int maxn = 5e5+100;
int point[maxn];
struct node
{
int l, r;
ll cnt;
}tree[4 * maxn];
int pos(int x, int cnt)
{
return lower_bound(point+1,point+1+cnt,x)-point;
}
void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].cnt=0;
if(l==r)return;
int mid=(l+r)/2;
build(ls(i),l,mid);
build(rs(i),mid+1,r);
}
void update(int i, int cnt, int p)
{
if (tree[i].l == tree[i].r)
{
tree[i].cnt+=cnt;
return;
}
int mid = tree[ls(i)].r;
if(p<=mid)update(ls(i),cnt,p);
else update(rs(i),cnt,p);
tree[i].cnt = tree[ls(i)].cnt + tree[rs(i)].cnt;
}
int kth(int i, int k)
{
if (tree[i].l == tree[i].r) return point[tree[i].l];
if (k <= tree[ls(i)].cnt) return kth(ls(i), k);
else return kth(rs(i), k - tree[ls(i)].cnt);
}
int op[maxn],x[maxn];
int main()
{
int q;
scanf("%d", &q);
for (int i=1;i<=q;i++)
{
scanf("%d %d",&op[i],&x[i]);
point[i]=x[i];
}
sort(point+1,point+1+q);
int cnt=unique(point+1,point+1+q)-(point+1);
build(1, 1, cnt);
for (int i = 1; i <= q; i++)
{
if (op[i] == 1)
{
update(1, 1, pos(x[i], cnt));
}
if (op[i] == 2)
{
update(1, -1, pos(x[i], cnt));
}
if (op[i] == 4)
{
int ans = kth(1, x[i]);
printf("%d\n", ans);
}
}
return 0;
}