【Codeforces Gym 100739 A】Queries
阿新 • • 發佈:2019-05-12
所有 有一種 個數 pre ldo 一段 可能 向上 如果 和\(0\)的。
題意:給\(n\)個數\(a_{1..n}\),以及\(m\)個詢問,每個詢問如下:
1 p x
表示把第\(p\)位上的數改成\(x\)。2 a b
表示找出\(\sum_{a\le l\le r\le b}a_l\ xor\ \ldots\ xor\ a_r\)。
思路:線段樹。
首先肯定把位拆開來考慮,那麽我們建\(10\)棵線段樹。
每棵線段樹需要維護什麽呢?
首先肯定需要維護這一段中這一位的亦或和。
那麽我們知道亦或就是自己的逆運算,即\(xorsum(a,b)=xorPrefixSum(b)\ xor\ xorPrefixSum(a-1)\),所以我們需要存儲這一段所有的前綴亦或和中為\(1\)
同時肯定要把答案記錄下來。
那麽我們的線段樹的每個節點長這樣:
- sum,即亦或和
- odd,即前綴亦或和中為1的個數
- even,即前綴亦或和中為0的個數
- ans,即答案。
然後我們看看上推操作。
首先我們的sum=ls.sum^rs.sum
。
那麽我們分ls.sum
的情況討論。
如果ls.sum=0
,那麽我們的rs.odd
會加到odd中,rs.even
也是同理。
看ans會有什麽變化。
首先我們的ans肯定要從ls.ans和rs.ans中來,然後rs中的even可以和所有的ls中的odd配對,odd也同理。
如果ls.sum=1
就應該把所有的rs.even換成odd,odd換成even。
那麽我們在查詢的時候用zkw線段樹的方式,從左邊向上走一串,右邊走一串,分別"上推"成\(l\)和\(r\),最後把\(l\)和\(r\)合並即可。
還是不太好寫的吧。還有一種想法就是存前後綴的和中有多少\(0\)和\(1\)。這樣可能自然一點。畢竟和比差總是好的嘛。
【Codeforces Gym 100739 A】Queries