• 洛谷 P5283 【十二省联考2019】异或粽子 题解


    洛谷 P5283 【十二省联考2019】异或粽子题解

    2020-02-03 xiaoh

    题意

    给定一个有(n)个数的序列(a)((1leq n leq 5×10^5,1 leq a_i leq 4294967295)),求这个序列中前(k)大的异或区间和之和。((1leq k leq 2×10^5))

    题解

    看到“异或”和“区间和”,不难想到用可持久化Trie来维护整个序列的前缀和。接下来考虑如何求出前k大的元素。这让我们想到了洛谷 P1631 序列合并。我们可以以每个(i)([1,n]) 作为区间的r,借助可持久化Trie求出使异或和最大的l并放入堆。接下来依次取出堆顶,不妨设其对应的区间为 ([l_x,r_x]),且为对应(r_x)的所有左区间的第(k_x)大,那么我们就求出对应(r_x)的第(k_x+1)大元素并放入堆即可,很明显,这是可持久化Trie可以做到的。时间复杂度(O(kWlogn))((W)为位宽)。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    template<typename T>
    inline void read(T &x)
    {
    	x=0;
    	int f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
    	x*=f;
    	return;
    }
    template<typename T>
    void write(T x)
    {
    	if(x<0) putchar('-'),x=-x;
    	if(x>=10) write(x/10);
    	putchar(x%10+'0');
    	return;
    }
    const int MAXN=500010,W=33;
    int n,k;
    long long a[MAXN];
    long long s[MAXN];
    int tot=0;
    int trie[MAXN*(W+1)*2][2];
    int rt[MAXN];
    int sz[MAXN*(W+1)*2];
    void insert(int x,int k,int p,int q)
    {
    	if(k<0)
    	{
    		sz[q]++;
    		return;
    	}
    	int c=(s[x]>>k)&1;
    	trie[q][c^1]=trie[p][c^1];
    	trie[q][c]=++tot;
    	sz[trie[q][c]] = sz[trie[p][c]];
    	insert(x,k-1,trie[p][c],trie[q][c]);
    	sz[q]=sz[trie[q][0]]+sz[trie[q][1]];
    }
    void query(int p,long long x,int k,int rk,long long &ans)
    {
    	if(k<0) return;
    	int c=(x>>k)&1;
    	if(sz[trie[p][c^1]]>=rk) ans=(ans<<1)|1,query(trie[p][c^1],x,k-1,rk,ans);
    	else ans<<=1,query(trie[p][c],x,k-1,rk-sz[trie[p][c^1]],ans);
    }
    struct node{
    	long long x;
    	int rk,id;
    	friend bool operator <(node a,node b)
    	{
    		return a.x<b.x;
    	}
    };
    priority_queue<node> q;
    long long ans=0;
    int main()
    {
    	read(n),read(k);
    	sz[0]=0;
    	rt[0]=++tot;
    	insert(0,W,0,rt[0]);
    	for(int i=1;i<=n;i++) read(a[i]),s[i]=s[i-1]^a[i];
    	for(int i=1;i<=n;i++)
    	{
    		long long tmp=0;
    		rt[i]=++tot;
    		insert(i,W,rt[i-1],rt[i]);
    		query(rt[i],s[i],W,1,tmp);
    		q.push({tmp,1,i});
    	}
    	for(int i=1;i<=k;i++)
    	{
    		node tmp=q.top();q.pop();
    		ans+=tmp.x;
    		long long x=0;
    		query(rt[tmp.id],s[tmp.id],W,tmp.rk+1,x);
    		q.push({x,tmp.rk+1,tmp.id});
    	}
    	write(ans),putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    Spark的Shuffle机制
    Map Reduce的代码学习
    本地IDEA跑阿里云服务器Word Count
    HDFS的类学习和API基本操作
    本地IDEA(Windows)访问ECS服务器HBase
    本地IDEA访问ECS服务器HDFS
    阿里云ECS大数据环境搭建
    学会使用vue ui搭建项目
    用vue封装视频预览组件(手机端)
    项目中的部门使用级联选择器,编辑时初始化选中部门解决方案
  • 原文地址:https://www.cnblogs.com/xiaoh105/p/12256710.html
Copyright © 2020-2023  润新知