已知乙個長度為n的整數數列\(a_1,a_2,...,a_n\)給定查詢引數l、r,問在\(a_l,a_,...,a_r\)區間內,有多少子串行滿足異或和等於k。也就是說,對於所有的x,y (i ≤ x ≤ y ≤ r),能夠滿足\(a_x \bigoplus a_ \bigoplus ... \bigoplus a_y = k\)的x,y有多少組。
輸入格式:
輸入檔案第一行,為3個整數n,m,k。
第二行為空格分開的n個整數,即\(a_1,a_2,..a_n\)。
接下來m行,每行兩個整數\(l_j,r_j\),表示一次查詢。
輸出格式:
輸出檔案共m行,對應每個查詢的計算結果。
輸入樣例#1:複製
4 5 1
1 2 3 1
1 41 3
2 32 4
4 4輸出樣例#1:複製42
121對於30%的資料,\(1 ≤ n, m ≤ 1000\)
對於100%的資料,\(1 ≤ n, m ≤ 10^5, 0 ≤ k, a_i ≤ 10^5,1 ≤ l_j ≤ r_j ≤ n\)
首先我們明確一點。那就是異或的性質。
及\(a_1\) ^ \(a_2\) ^ \(a_3\) ^ \(a_4\) ^ \(a_5\)...
就同等於 \(sum_5\) ^ \(sum_0\) sum表示字首和
然後我們要知道怎麼去維護異或和為k是吧。
根據a^b=c可知 ac=k,ak=c。
所以我們只需要知道乙個字首和異或k的值與當前哪些序列的值相等。然後加上那些序列的個數即可。
那麼最後讓莫隊在字首和上移動,因為當前字首和就是乙個序列對吧。
關於有人不懂子串行是怎麼實現的。
以1到5為例,依次放入字首和。
用莫隊對當前異或值進行計數。然後每放入乙個,就更新異或值和讓答案加上(異或值^k)的數量。這個過程就相當於\(sum_r\) ^ \(sum_\)
#include#include#include#include#includeusing namespace std;
int cnt[500001],val[500001],k,n,m,tmp,sum,ans[500001],ch[500001];
struct nodet[500001];
int read()
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}bool cmp(node a,node b)
ans[t[i].id]=sum;
}for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}int main()
CQOI2018 異或序列
哈哈哈我竟然秒切了省選題 莫隊 異或。考慮異或的性質,乙個數同時異或兩次等於沒有進行操作。那麼我們設a i 為前i個數的異或和,顯然對於乙個區間 l,now a l 1 oplus a now 就是這個區間裡面所有的數的異或和。如果 a l 1 oplus a now k 那麼ans 這等同於 a ...
CQOI 2018 異或序列
給出乙個長為 n 的數列 a 和 k 多次詢問 對於乙個區間 l i,r i 問區間內有多少個不為空的子段異或和為 k 注意到一件有趣的事,就是每次詢問的 k 相同。因為 a oplus a 0 所以子段異或問題可以看作字首異或和的異或,即 a i oplus a i 1 oplus.oplus a...
CQOI2018 交錯序列
這個題簡直有毒,o a b 3logn 的做法不卡常只比 o 2 n n 多 10 分 看到 a 和 b 簡直小的可憐,於是可以往矩陣上聯想 發現這個柿子有些特殊,好像可以二項式定理搞一搞 於是 x ay b 可以寫成 n y ay b 於是接下來就二項式定理好了 n y ay b sum a bi...