CQOI 2018 異或序列

2022-03-30 01:17:14 字數 1504 閱讀 9515

\(\\\)

給出乙個長為 \(n\) 的數列 \(a\) 和 \(k\),多次詢問:

對於乙個區間 \([l_i,r_i]\),問區間內有多少個不為空的子段異或和為 \(k\) 。

\(\\\)

注意到一件有趣的事,就是每次詢問的 \(k\) 相同。

因為 \(a\oplus a=0\),所以子段異或問題可以看作字首異或和的異或,即

\[a[i]\oplus a[i+1]\oplus...\oplus a[j]=sum[i-1]\oplus sum[j]

\]其中 \(sum[i]=a[1]\oplus a[2]\oplus...\oplus a[i]\) 。

那麼問題轉化為,存在對少對 \(i,j\in[l_i-1,r_i],i!=j\) ,滿足

\[sum[i]\oplus sum[j]=k

\]注意區間問題,因為區間做差的原理是減掉 \(l-1\) 。

然後可以注意到,乙個值 \(x\) 若想要構成 \(k\) ,其對應的另乙個值是固定的。

也就是說,我們的組合方案是確定的。

當新加入乙個可選值 \(x\) ,我們的方案數就會 \(+cnt[x^k]\) ,其中 \(cnt[i]\) 表示當前含有可選值 \(i\) 的個數。

可以證明,這種計數方式不會算重,因為每個數字加入時只會計算當前已經有對應的值。

當去掉乙個值的時候,方案數 \(-cnt[x^k]\) 即可。

\(\\\)

還有乙個問題,就是關於 \(k=0\) 的情況。

此時每個值顯然不能計算上自己和自己異或的貢獻。

刪除時當然也要注意不能多減掉自己異或自己的情況。

只需在adddel的時候交換一下操作順序即可,具體看**。

\(\\\)

突然失智......debug 2h 竟只是因為 \(l\) 沒有減 \(1\) ......

還要注意,剛開始 \(0\) 號位置也有乙個貢獻。

#include#include#include#include#include#include#include#define n 100010

#define r register

#define gc getchar

using namespace std;

typedef long long ll;

inline ll rd()

while(isdigit(c))

return f?-x:x;

}ll n,m,k,ans,bl[n],cnt[1<<18],s[n],res[n];

struct qq[n];

inline bool cmp1(q x,q y)

while(nowlq[i].r)

res[q[i].id]=ans;

} for(r ll i=1;i<=m;++i) printf("%lld\n",res[i]);

return 0;

}

CQOI2018 異或序列

哈哈哈我竟然秒切了省選題 莫隊 異或。考慮異或的性質,乙個數同時異或兩次等於沒有進行操作。那麼我們設a i 為前i個數的異或和,顯然對於乙個區間 l,now a l 1 oplus a now 就是這個區間裡面所有的數的異或和。如果 a l 1 oplus a now k 那麼ans 這等同於 a ...

CQOI2018 異或序列

已知乙個長度為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有多少組。輸入格式 輸入...

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