本題可以算線段樹的基本操作了,進入正題吧:
我們線段樹中儲存三個變數:
做題過程分為建樹,單點修改和查詢 (很經典了吧)
本題在建樹和單點修改時只有一點與其他節點不同,就是合併節點資訊,在這裡略作解釋:
首先是最簡單直接賦值:
\(rs_x=rs_,ls_x=ls_\)
\(sum_x=sum_+sum_+[ls_==1\&\&rs_==1]\)
另外注意一點,當\(sonl\)的區集中全是\(x\)時,\(rs_x\)是要等於\(rs_\)的,而且易證得,如果\(sum_==0\&\&rs_==0\&\&ls_==0\),則可以說明左兒子全是\(x\),因此合併部分**如下:
inline void update(int x)
再就是查詢了,這裡需要用到乙個小技巧,線段樹的遍歷順序是從左往右的,所以我們每遇到乙個合法區間,和前乙個遇到的合法區間合併計算答案就好了,同樣需要注意全為\(x\)的情況。#include#define re register
using namespace std;
inline int read()
const int n=200005;
int n,m,sum[n<<2],ans;
bool ls[n<<2],rs[n<<2],last;
char ch[n],s[1];
inline void update(int x)
void build(int l,int r,int x)
re int mid=l+r>>1;
build(l,mid,x<<1),build(mid+1,r,x<<1|1);
update(x);
}void change(int l,int r,int x,int p,char a)
re int mid=l+r>>1;
if(p<=mid) change(l,mid,x<<1,p,a);
else change(mid+1,r,x<<1|1,p,a);
update(x);
}void ask(int l,int r,int x,int l,int r)
re int mid=l+r>>1;
if(l<=mid) ask(l,mid,x<<1,l,r);
if(r>mid) ask(mid+1,r,x<<1|1,l,r);
}inline void fre()
int main()
else
}return 0;
}
妖夢斬木棒
顯然,大概率是用線段樹維護區間資訊。考慮區間合併 每次合併的時候我們只關注左區間靠右的第乙個非x符號和右區間的靠左第乙個非x符號。然後我們維護一下即可,不過我們要注意如果當前區間只有乙個非x字元,那麼合併之後就沒了。ac pragma gcc optimize ofast funroll all l...
P3799 妖夢拼木棒
有 nn根木棒,現在從中選 4 根,想要組成乙個正三角形,問有幾種選法?答案對 10 9 7取模。輸入 第一行乙個整數 n。第二行 n 個整數,第 i 個整數 a i,代表第 i 根木棒的長度。輸出 一行乙個整數代表答案。主要是對長度進行計算和處理 因為ai的數值偏小。注意 using namesp...
洛谷P3799 妖夢拼木棒
題目鏈結 上道題中,妖夢斬了一地的木棒,現在她想要將木棒拼起來。有n根木棒,現在從中選4根,想要組成乙個正三角形,問有幾種選法?第一行乙個整數n 第二行n個整數,a1,a2,an 0 一行乙個整數,對1e9 7取模 4 1 1 2 2 對於30 的資料 n 5000 對於100 的資料 n 1000...