Это легко сделать, используя дерево сегментов структура данных со сложностью O (Q * log (10 ^ 9))
- Мы должны использовать так называемые "разреженные"дерево сегментов, так что мы создаем узлы только при необходимости, а не все узлы.
- В каждом узле мы будем сохранять количество элементов в диапазоне [L, R]
- Теперь добавления некоторого элементаВремя y может быть легко сделано путем обхода дерева сегментов от корня до листа и обновления значений (также создавая узлы, которые еще не существуют). Поскольку высота дерева сегментов является логарифмической, это занимает log N раз, когда N - это начальная длина нашего интервала (10 ^ 9)
- Поиск k-го элемента можно легко выполнить с помощью бинарного поиска по дереву сегментов, поскольку на каждомВ узле мы знаем количество элементов в некотором диапазоне, мы можем использовать эту информацию для перемещения влево или вправо к элементу, который содержит k-тый
Пример кода (C ++):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int sz = 31*4*5*100000;
ll seg[sz];
int L[sz],R[sz];
int nxt = 2;
void IncNode(int c, int l, int r, int idx, int val)
{
if(l==r)
{
seg[c]+=val;
return;
}
int m = (l+r)/2;
if(idx <= m)
{
if(!L[c])L[c]=nxt++;
IncNode(L[c],l,m,idx,val);
}
else
{
if(!R[c])R[c]=nxt++;
IncNode(R[c],m+1,r,idx,val);
}
seg[c] = seg[L[c]] + seg[R[c]];
}
int FindKth(int c, int l, int r, ll k)
{
if(l==r)return r;
int m = (l+r)/2;
if(seg[L[c]] >= k)return FindKth(L[c],l,m,k);
return FindKth(R[c],m+1,r,k-seg[L[c]]);
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int Q;
cin>>Q;
int L = 0, R = 1e9;
while(Q--)
{
int type;
cin>>type;
if(type==1)
{
int x,y;
cin>>x>>y;
IncNode(1,L,R,x,y);
}
else
{
int k;
cin>>k;
cout<<FindKth(1,L,R,k)<<"\n";
}
}
}