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