1. 程式人生 > >【Codeforces Gym 100739 A】Queries

【Codeforces Gym 100739 A】Queries

所有 有一種 個數 pre ldo 一段 可能 向上 如果

題意:給\(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\)

\(0\)的。

同時肯定要把答案記錄下來。

那麽我們的線段樹的每個節點長這樣:

  • 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