雅禮培訓 Problem A 線段樹

2022-02-27 17:28:36 字數 1650 閱讀 3474

維護一段區間,支援求區間最大值,區間且,區間或

\(n,q<=2*10^5\)

我們用線段樹維護區間最大值

對於and和or運算,

and實質就是強行把一些位改為0

or實質就是強行把一些位改為1

那麼由線段樹區間標記的思想,如果某個操作對整個區間的影響是相同的,並且能很快維護出當前節點資訊,我們就可以通過打標記進行優化

顯然,當需要操作的那些位在整個區間都是相同的,我們就可以打上乙個標記

對於統計區間相同位置,有乙個小技巧:

維護區間or和區間and

and中為1的位區間都為1

or中為0的位區間都為0

二者整合起來就可以得到區間相同的位置集合

如果區間總是不相同,複雜度會不會變差呢?

很顯然,每次操作只能使所有位置相同的越來越多,而原來不同的位置經操作後一定變為相同

所以複雜度依舊是\(o(nlogn)\)

#include#include#include#include#define ll long long int

#define rep(i,n) for (int i = 1; i <= (n); i++)

#define redge(u) for (int k = h[u]; k; k = ed[k].nxt)

#define ls (u << 1)

#define rs (u << 1 | 1)

using namespace std;

const int maxn = 200005,maxm = 100005,maxv = (1 << 20) - 1,inf = 1000000000;

inline int read()

while (c >= 48 && c <= 57)

return out * flag;

}int mx[4 * maxn],and[4 * maxn],or[4 * maxn];

int vand[4 * maxn],vor[4 * maxn];

int n,a[maxn],q;

void work_and(int u,int v)

void work_or(int u,int v)

void upd(int u)

void pd(int u)

if (or[u])

}void build(int u,int l,int r)

int mid = l + r >> 1;

build(ls,l,mid);

build(rs,mid + 1,r);

upd(u);

}void modify(int u,int l,int r,int l,int r,int v,int opt)

} else

} }pd(u);

int mid = l + r >> 1;

if (mid >= l) modify(ls,l,mid,l,r,v,opt);

if (mid < r) modify(rs,mid + 1,r,l,r,v,opt);

upd(u);

}int query(int u,int l,int r,int l,int r)

int main()

return 0;

}

湖南雅禮培訓 1 6

懷疑以前學了假的strling數,看了乙個很相似的題bzoj2159的題解,終於理解了本題的solution include include include define maxn 200010 define mod 998244353 using namespace std intn,m,k,nu...

雅禮集訓 小C的線段樹

標籤 dp 輸出0可以騙到5分 出題人說這是最簡單的一題,果然題目順序和難度無關qwq 當n m時不存在合法的序列,所以答案為0 我們可以將區間 l,r 看成括號匹配 位置i最終的值就是左邊的左括號數量減去左邊的右括號數量 設f i l r 表示i位置左邊有l個左括號,r個右括號的方案數,ans i...

2018雅禮集訓1 18 日記 線段樹

真tm線段樹神題。設 l,r 複雜值為tl r首先對於詢問 l r 把問題轉化為 n i 1 nj i ti,j l 1i 1 l 1 j it i,j ni r 1 nj i ti,j 我們先考慮字首的,字尾的反過來再做一遍就是了。我們設f i 為 i j 1t j,i 那麼fi 的字首和就是所求...