維護一段區間,支援求區間最大值,區間且,區間或
\(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 的字首和就是所求...