[英]Appropriate data structure for add and find queries
我有兩種類型的查詢。
1 XY
在集合中添加元素 X,Y 次。
2 牛
查詢次數 < 5 * 10^5
X < 10^9
Y < 10^9
在已排序的集合中查找第 N 個元素。
我嘗試了 STL 設置,但沒有成功。
我認為我們需要平衡樹,每個節點都包含兩個數據值。
第一個值將是元素 X。另一個將是小於或等於值的元素的所有 Y 的前綴總和。
當我們添加元素 X 時,找到第一個值的預處理器。將與預處理器關聯的第二個值添加到 Y。
當找到第 N 個元素時。 在樹(第二個值)中搜索立即低於 N 的值。
如何高效地實現這種數據結構?
這可以使用復雜度為 O(Q*log(10^9)) 的分段樹數據結構輕松完成
示例代碼(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";
}
}
}
在每個節點中維護前綴和是不切實際的。 這意味着每次添加新節點時,都必須更新樹中每個節點的前綴和。 相反,您需要維護子樹總和:每個節點應包含其自己的鍵和所有后代的鍵的 Y 值的總和。 更新樹時維護子樹總和應該很簡單。
當您回答類型 2 的查詢時,在每個節點上,如果 N 小於或等於左孩子的子樹總和值 S(我假設 N 是 1 索引),您將下降到左子樹。 否則,從 N 中減去 S + 1 並下降到右子樹。
順便說一句,如果事先知道整個 X 值集,那么您可以使用范圍樹或二叉索引樹來代替平衡 BST。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.