題解報告 P3797 妖夢斬木棒

2022-07-22 20:30:19 字數 1290 閱讀 7430

本題可以算線段樹的基本操作了,進入正題吧:

我們線段樹中儲存三個變數:

做題過程分為建樹,單點修改和查詢 (很經典了吧)

本題在建樹和單點修改時只有一點與其他節點不同,就是合併節點資訊,在這裡略作解釋:

首先是最簡單直接賦值:

\(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...