線段樹訓練

2022-08-20 06:30:12 字數 1763 閱讀 3311

d - hdu6703

題意:給乙個長度為n且互不相同的陣列。有m個操作,操作1是給a[pos]加上1000000,操作2是查詢在1-r沒有出現過同時大於k的值,並使其最小。

一種做法就是權值線段樹,每個節點維護該權值的下標,那麼原題就轉化為查詢[k,n]範圍內大於r的值,位置盡量靠左,即可使答案最小。

#include #define int long long

using namespace std;

const int n = 2e5 + 10;

struct segtree

void up(int k)

void build(int k, int l, int r, vector&b)

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

build(k<<1, l, m, b);

build(k<<1|1, m + 1, r, b);

up(k);

} void upd(int k, int l, int r, int p, int v)

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

if (p <= m) upd(k<<1, l, m, p, v);

else upd(k<<1|1, m + 1, r, p, v);

up(k);

} void upd(int p, int v)

int qry(int k, int l, int r, int p, int v)

int m = (l + r) >> 1, res = 0;

if (p <= m && t[k<<1] > v) else res = qry(k<<1|1, m + 1, r, p, v);

return res;

} int qry(int p, int v)

};signed main()

segtree seg(n, b);

int la = 0;

while (m--) else

} }return 0;

}

e - codeforces 1418g

題意:給乙個長度為n的陣列,問你有多少個這樣的區間,使得區間中每個數字恰好出現3次

參考部落格: blog.csdn.net/qq_45458915/article/details/108681107

#include #define ll long long

using namespace std;

const int n = 2e5 + 10;

struct segtree ;

int n;

vectort;

segtree(int n): n(n), t(n<<2) {}

void up(int k, int l, int r)

void upd(int k, int l, int r, int ql, int qr, int v)

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

if (ql <= m) upd(k<<1, l, m, ql, qr, v);

if (qr > m) upd(k<<1|1, m + 1, r, ql, qr, v);

up(k, l, r);

} void upd(int l, int r, int v)

};signed main()

cout << ans << '\n';

return 0;

}

10 25演算法訓練 裸線段樹

題目大意 對n 1 n 50000 個數進行連續進行m 1 m 200000 次詢問 問1 n之間任意連續區間最大值和最小值之差。之前學過線段樹,學的是模版題,求解的問題是在一段區間內任意加減,然後再詢問任意一段之區間的和。這次的問題和之前學的模版題相同之處是 查詢的是一段連續區間的資訊。所以之後的...

演算法訓練 操作格仔 線段樹

問題描述 有n個格仔,從左到右放成一排,編號為1 n。共有m次操作,有3種操作型別 1.修改乙個格仔的權值,2.求連續一段格仔權值和,3.求連續一段格仔的最大值。對於每個2 3操作輸出你所求出的結果。輸入格式 第一行2個整數n,m。接下來一行n個整數表示n個格仔的初始權值。接下來m行,每行3個整數p...

高手訓練 線段樹 棧的維護

time limit 20 sec memory limit 512 mb 從前有個棧,一開始是空的。你寫下了 m 個操作,每個操作形如 k v 若 k 0,代表往棧頂加入乙個數 v 若 k 1,則代表從棧頂彈出 v 個數,如果棧中的元素少於 v 個,則全部彈出。接著你又進行了 q 次修改,每次你會...