[十二省联考2019]异或粽子(可持久化tire,堆)
Description
题目描述
小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。
小粽面前有 n 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 1 到 n。
第 i 种馅儿具有一个非负整数的属性值 a_i。每种馅儿的数量都足够多,即小粽不会因为缺少原料而做不出想要的粽子。
小粽准备用这些馅儿来做出 k 个粽子。
小粽的做法是:选两个整数数 l, r,满足 1⩽l⩽r⩽n,
将编号在 [l, r] 范围内的所有馅儿混合做成一个粽子,所得的粽子的美味度为这些粽子的属性值的异或和。
(异或就是我们常说的 xor 运算,即 C/C++ 中的 ˆ 运算符或 Pascal 中的 xor 运算符)
小粽想品尝不同口味的粽子,因此它不希望用同样的馅儿的集合做出一个以上的 粽子。
小粽希望她做出的所有粽子的美味度之和最大。请你帮她求出这个值吧!
输入格式
第一行两个正整数 n, k,表示馅儿的数量,以及小粽打算做出的粽子的数量。
接下来一行为 n 个非负整数,第 i 个数为 a_i,表示第 i 个粽子的属性值。 对于所有的输入数据都满足:
1⩽n⩽5×105, 1⩽k⩽min{2n(n−1),2×105}, 0⩽ai⩽4294967295。
输出格式
输出一行一个整数,表示小粽可以做出的粽子的美味度之和的最大值。
Sol
想来一年前去省选当非正式选手时我还是个不知道异或是什么的蒟蒻。。。
(看到“异或”慌得一批,这是什么!!!)
年年岁岁题相似,岁岁年年人不同
正文:
设a[ i ]:1~i 的异或和
对于每个 i ,建立一颗trie树储存 1~i 的 a;
在这棵trie树上搜索与a[i]异或所得值最大的一个数,并边找边删去它,把这个所得值和i加入大根堆中
1~n扫完后开始在堆中找最大的k个数,每弹出一个堆顶要再在它的trie树里找到并删去最大值,再加入堆中
可是这样数组太大,于是用可持久化优化,记得加数和删树时都要重建树,不然会对共用节点的其他树造成影响
Code
#include <cstdio> #include <cstdlib> #include <queue> #define ll long long using namespace std; const int N=1e6+10; struct node { int ch[2],sum; }f[N*80]; int n,k,rt[N],tot,cnt[N]; ll a[N],ans,an=1; void build(int x,int y,int t,ll pos) { if(t<0) return ; int wh=(pos>>t)&1; f[x].ch[!wh]=f[y].ch[!wh]; f[x].ch[wh]=++tot; f[f[x].ch[wh]].sum=f[f[y].ch[wh]].sum+1; build(f[x].ch[wh],f[y].ch[wh],t-1,pos); } struct mode { int id; ll v; bool operator <(const mode &o)const { return v<o.v; } }; priority_queue <mode> q; ll get(int x,int y,int t,ll pos) { if(t<0) return 0; int wh=(pos>>t)&1; int yy=f[y].ch[!wh],zz=f[y].ch[wh]; if(f[yy].sum>0) { f[x].ch[wh]=zz; f[x].ch[!wh]=++tot; f[tot].sum=f[yy].sum-1; return (an<<t)+get(f[x].ch[!wh],yy,t-1,pos); } else { f[x].ch[!wh]=yy; f[x].ch[wh]=++tot; f[tot].sum=f[zz].sum-1; return get(f[x].ch[wh],zz,t-1,pos); } } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); a[i]^=a[i-1]; rt[i]=++tot; build(rt[i],rt[i-1],32,a[i-1]); } for(int i=1;i<=n;i++) { cnt[i]++; int nw=++tot; ll xx=get(nw,rt[i],32,a[i]); rt[i]=nw; q.push((mode){i,xx}); } while(k--) { mode tp=q.top(); q.pop(); ans+=tp.v; if(++cnt[tp.id]<=tp.id) { int nw=++tot; ll xx=get(nw,rt[tp.id],32,a[tp.id]); rt[tp.id]=nw; q.push((mode){tp.id,xx}); } } printf("%lld\n",ans); return 0; }

浙公网安备 33010602011771号