CF 19D Points 線段樹 平衡樹

2022-04-04 03:47:01 字數 1188 閱讀 8555

在平面上進行三種操作:

1、add x y:在平面上新增乙個點(x,y)

2、remove x y:將平面上的點(x,y)刪除

3、find x y:在平面上尋找乙個點,使這個點的橫座標大於x,縱座標大於y,而且要求他的橫座標盡量小,如果有多個點滿足,則選取橫座標盡量小的前提下,縱座標最小的點。

方法:將橫座標x離散化,每乙個座標x對應的y用一顆平衡樹維護(c++中的set),則這顆平衡樹支援增加和刪除以及查詢比y大的最小值的操作。

在此基礎上,對於每乙個詢問,只需要遍歷大於x的set,並且找到最小的y即可。但是這樣子依次向後遍歷的複雜度為o(n)的,所以要用一顆線段樹來維護橫座標區間段裡面y的最大值,這樣就可以在o(logn)的複雜度內找到最接近x的橫座標(而且滿足當前座標的最大縱座標大於y),然後再set裡面查詢最小的縱座標即可。

#include #include #include #include #include using namespace std;

#define n 200100

int n, m, a[n], my[n<<2];

seta[n];

char s[10];

struct node q[n];

int idx(int v)

void update(int x, int l, int r, int rt)

int mid = (l + r) >> 1;

if (x <= mid) update(x, l, mid, rt<<1);

else update(x, mid+1, r, rt<<1|1);

my[rt] = max(my[rt<<1], my[rt<<1|1]);

}int query(int x, int y, int l, int r, int rt)

int mid = (l + r) >> 1;

int t = 0;

if (x < mid && my[rt<<1] > y) t = query(x, y, l, mid, rt<<1);

if (t == 0 && my[rt<<1|1] > y) t = query(x, y, mid+1, r, rt<<1|1);

return t;

}int main() {

scanf("%d", &n);

m = 0;

for (int i=0; i

CF 19D Points 線段樹 平衡樹

在平面上進行三種操作 1 add x y 在平面上新增乙個點 x,y 2 remove x y 將平面上的點 x,y 刪除 3 find x y 在平面上尋找乙個點,使這個點的橫座標大於x,縱座標大於y,而且要求他的橫座標盡量小,如果有多個點滿足,則選取橫座標盡量小的前提下,縱座標最小的點。方法 將...

cf474e Pillars 線段樹優化dp

有n個柱子,每個柱子有乙個高度hi h i,每個柱子可以跳到它後面高度與它相差大於d的柱子 即 h i hj d hi hj d 求最多可以跳多少個柱子an si m ax a nsj 1 hi h j d且 ja ns i ma x an sj 1 h i hj d且 j 因此建立一棵線段樹,節點...

cf 1187D 逆序對(線段樹)

題意 給你兩個均有n個數的陣列,現在你可以對a陣列中的任意區間進行sort操作,問你在sort完之後能不能得到b陣列。做法 這個是真的想不到啊。想法2200分的題目,大概的意思就是,因為可以對其中的任意區間進行操作,等於是去找逆序對的樣子,for每個數,當前數字在原陣列位置前不能有更小的未被消去的值...