CSU 1258 維護序列 線段樹

2021-07-30 07:32:20 字數 1706 閱讀 5928

description

現在有乙個n個整數組成的序列,這n個整數的標號分別為1, 2, …, n,對這個序列一共進行兩類操作:

① 1 x y:表示將第x個和第y個(包括x、y)整數之間的所有整數的二進位制的最低位的1變為0,如果某個整數的值為0,則不對這個整數做任何改變。

② 2 x y :表示你需要回答第x個和第y個(包括x、y)整數之間的所有整數異或的結果。

input

輸入包含多組測試資料。

對於每組測試資料,第一行包含兩個正整數n(2<=n<=10^4)、m(1<=m<=10^5),表示這個序列一共有n個不超過2^30的整數,你需要處理m次操作。接下來一共有m行,每行均描述了一種操作。

output

對於每個第②類操作,用一行輸出乙個整數表示回答的結果。

sample input

3 4

3 6 0

2 2 2

2 1 2

1 1 3

2 1 3

sample output

6 5

6max_n 寫成題中的上限1e5,而10005 會re,不知道為什麼

由於對區間去除尾數零,區間是會取向規整化的,都有變為 0 的趨勢。

於是我們記錄區間的或,如果為零,怎麼操作都是零,change和query時直接return 即可

//這是乙個非常關鍵的剪枝,否則就變成單純的暴力題了

#include

#include

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f

#define max_n 20005

using

namespace

std;

typedef

long

long ll;

struct nodedat[max_n*3];

int res[max_n];

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

build(k<<1,l,(l+r)/2);

build(k<<1|1,(l+r)/2+1,r);

dat[k].ans=dat[k<<1].ans^dat[k<<1|1].ans;

dat[k].ans0=dat[k<<1].ans0|dat[k<<1|1].ans0;

}void change(int k,int l,int r,int ql,int qr)

change(k<<1,l,(l+r)/2,ql,qr);

change(k<<1|1,(l+r)/2+1,r,ql,qr);

dat[k].ans=dat[k<<1].ans^dat[k<<1|1].ans;

dat[k].ans0=dat[k<<1].ans0|dat[k<<1|1].ans0;

}int query(int k,int l,int r,int ql,int qr)

int t1=query(k<<1,l,(l+r)/2,ql,qr);

int t2=query(k<<1|1,(l+r)/2+1,r,ql,qr);

return t1^t2;

}int main()

}return

0;}

CSUOJ 1258 維護序列

線段樹題目。此題的更新必須要更新到葉節點,否則的話,會出現錯誤。對於乙個int範圍內的數字,更新若干次 最多32次 後必然會變成0,那麼此時在更新就沒有意義了。那麼我們可以用lazy標記,當某個區間的數字全部變為0後,我們將這個區間做上標記。那麼這個區間就不可能在被更新,這樣就可以提高效率,減去不必...

線段樹 AHOI 2009 維護序列

老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列中的一段數全部乘乙個值 2 把數列中的一段數全部加乙個值 3 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模p的值。第一行兩個整數n和p 1 p 100...

AHOI2009 維護序列 線段樹

老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為n的數列,不妨設為a1,a2,an 有如下三種操作形式 1 把數列中的一段數全部乘乙個值 2 把數列中的一段數全部加乙個值 3 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模p的值。線段樹,打個乘法lazy標記即可 i...