十二省聯考 2019 異或粽子

2021-09-20 15:38:23 字數 1197 閱讀 2406

題目鏈結

演算法:首先把字首異或和統計出來,再將得到的每乙個字首異或和(包括pre[0]=0),塞進字典樹中,接下來有乙個貪心的思路:每當我拿著其中乙個異或和的值時,我在字典樹中盡可能找二進位制高位與其對應的位不相同的異或和,這樣兩者異或運算後,所得值最大。

所以我們有了這樣乙個思路,對於每乙個pre[i](1<=i<=n,忘說了pre[i]=co[1]^co[2]......^co[i]),我們找到以第i位為端點(並不一定是左端點或右端點)的區間中,異或和最大的是多少,並將n個最大值塞入乙個堆中。接下來每次操作,我們將n個數中最大的取出,累計入ans,再將該最大值對應的位置,能產生的次小的異或值插入堆中(就是取出以第i位為端點的區間中,第k+1大的異或值)。

考慮怎麼計算第k大,我們可以預處理出字典樹每乙個子樹的大小,那麼再利用前面那個思路的性質,可以用類似treap的演算法算出第k打的異或和。最後需要注意的是,由於乙個區間有兩個端點,可能會重複計算一次,那麼在這種情況下,我們取前2*k大的異或和,最後答案/2即可。

code:

#include#define rep(i,j,k) for(int i=j;i<=k;i++)

#define rep2(i,j,k) for(int i=j;i>=k;i--)

using namespace std;

templatevoid read(t &num)

while(c>='0'&&c<='9')

num*=f;

}templatevoid qwq(t x)

templatevoid write(t x)

qwq(x);putchar('\n');

}long long co[500010];long long pre[500010];

struct wzytree[20000010];

int tot=1;int siz[20000010];

inline void change(long long x)else if(rk<=siz[tree[ret].pos[tmp^1]])else

}return ans;

}int main()

rep(i,0,n)

rep(i,0,n)

long long ans=0;

rep(i,1,2*k)

}write(ans/2);

return 0;

}

十二省聯考2019 異或粽子

點此看題 方法1 發現這道題k kk很小,先考慮用字首和表示異或和,建出一顆tire text tire 樹,然後把每個點的最優值丟進優先佇列中 因為其他值沒有這個值優 然後依次取出,再把次大值塞進去。由於每個區間會被統計兩次,所以我們找2k2k 2k次,最後把答案除以2 22即可。方法2 和k k...

十二省聯考2019 異或粽子

其實和超級鋼琴那個題思路挺像的,就是我們弄乙個二元組,乙個pos,乙個sum。求一下字首異或和,然後在它pos前面的01trie裡面查詢第k大即可。如下 luogu judger enable o2 include include include include include include de...

十二省聯考2019 異或粽子

給出乙個序列 定義乙個區間 的價值為 到 的所有數的異或和,價值前 大的區間的價值和 我們記 表示前 個數的異或和,那麼乙個區間 的價值就是 然後考慮將 插入到乙個可持久化 中,然後用堆維護每個 所能得到的最大值,然後依次取出前 項,每次取出後再在可持久化 上面刪掉乙個數就好了 created ti...