權值線段樹,每個葉子結點都視為點的權值,在進行操作時要離散
您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
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
101 106465
4 11 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]
**示例 :
#define ll long longconst ll maxn = 1e5+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;
#define lson k<<1
#define rson k<<1|1
struct pp
pre[maxn];
ll s[maxn];
ll k = 1;
struct node
t[maxn<<2];
void build(ll l, ll r, ll k)
void pushup(ll k)
void update(ll pos, ll pt, ll k)
ll m = (t[k].l+t[k].r)>>1;
if (pos <= m) update(pos, pt, lson);
else update(pos, pt, rson);
pushup(k);
}ll ans = 0;
void query3(ll l, ll r, ll k)
ll m = (t[k].l+t[k].r)>>1;
if (l <= m) query3(l, r, lson);
if (r > m) query3(l, r, rson);
}void query4(ll x, ll k)
ll m = (t[k].l+t[k].r)>>1;
if (t[lson].num >= x) query4(x, lson);
else query4(x-t[lson].num, rson);
}int main()
sort(s+1, s+k);
k = unique(s+1, s+k)-s;
//for(int i = 1; i < k; i++) printf("%lld ", s[i]);
build(1, n, 1);
for(ll i = 1; i <= n; i++)
else if (pre[i].pt == 2)
else if (pre[i].pt == 3)
else if (pre[i].pt == 4)
else if (pre[i].pt == 5)
else
}return 0;
}
權值線段樹
維護全域性的值域資訊,每個節點記錄的是該值域的值出現的總次數。使用二分的思想 離散化的時候,需要用到 支援查詢全域性k小值,全域性rank,前驅,後繼等。單詞操作時間複雜度為o logn 空間複雜度為o n 相對於平衡樹的優勢 簡單,速度快 劣勢 值域較大時,我們需要離散化,變成離線資料結構 我認為...
權值線段樹
include using namespace std int n,m,tre 10003 4 laz 10003 4 void pushdown int num void update int num,int le,int ri,int x,int y,int z pushdown num int...
權值線段樹
權值線段樹是線段樹的一種,但是它與線段樹不同 線段樹的每個結點是用來維護一段區間的最大值或總和 而權值線段樹的每個結點儲存的一段區間有多少個數 權值線段樹主要用來查詢區間第k大或者第k小的值 現在有乙個陣列x 10 對陣列排序後為x 10 每個數的個數如下 1 32 2 3 24 1 5 18 1 ...