luoguP5283 [十二省联考2019]异或粽子

题意

类似超级钢琴,找最优解用可持久化trie。

code:

#include<bits/stdc++.h>
using namespace std;
#define re register
typedef long long ll;
const int maxn=5*1e5+10;
int n,m,tot;
int root[maxn],last[maxn*40*2];
int trie[maxn*40][2];
ll ans;
ll a[maxn],sum[maxn];
struct node
{
	int x,l,r,t;ll val;
	bool operator<(const node& a)const{return val<a.val;}
};
priority_queue<node>q;
inline ll read()
{
	char c=getchar();ll res=0,f=1;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
	return res*f;
}
void insert(int pre,int now,int t,ll k,int id)
{
	if(t<0){last[now]=id;return;}
	int c=(k>>t)&1;
	if(pre)trie[now][c^1]=trie[pre][c^1];
	trie[now][c]=++tot;
	insert(trie[pre][c],trie[now][c],t-1,k,id);
	last[now]=max(last[trie[now][0]],last[trie[now][1]]);
}
int query(int now,int t,ll k,int lim)
{
	if(t<0)return last[now];
	int c=(k>>t)&1;
	if(last[trie[now][c^1]]>=lim)return query(trie[now][c^1],t-1,k,lim);
	else return query(trie[now][c],t-1,k,lim);
}
int main()
{
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	n=read(),m=read();
	for(re int i=1;i<=n;i++)a[i]=read(),sum[i]=sum[i-1]^a[i];
	root[0]=++tot;last[0]=-1;insert(0,root[0],35,0,0);
	for(re int i=1;i<=n;i++)root[i]=++tot,insert(root[i-1],root[i],35,sum[i],i);
	for(re int i=1;i<=n;i++)
	{
		int pos=query(root[n],35,sum[i-1],i);
		//cerr<<(sum[pos]^sum[i-1])<<endl;
		q.push((node){i,i,n,pos,sum[pos]^sum[i-1]});
	}
	while(m--)
	{
		node now=q.top();q.pop();
		ans+=now.val;
		if(now.t>now.l)
		{
			int pos=query(root[now.t-1],35,sum[now.x-1],now.l);
			q.push((node){now.x,now.l,now.t-1,pos,sum[now.x-1]^sum[pos]});
		}
		if(now.t<now.r)
		{
			int pos=query(root[now.r],35,sum[now.x-1],now.t+1);
			q.push((node){now.x,now.t+1,now.r,pos,sum[now.x-1]^sum[pos]});		
		}
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2019-12-10 11:38  nofind  阅读(75)  评论(0编辑  收藏  举报