• 【洛谷5283】[十二省联考2019] 异或粽子(可持久化Trie树+堆)


    点此看题面

    大致题意: 求前(k)大的区间异或和之和。

    可持久化(Trie)

    之前做过一些可持久化(Trie)树题,结果说到底还是主席树。

    终于,碰到一道真·可持久化(Trie)的题目。

    其实它的实现与主席树也是类似的。

    大致思路

    首先,我们统计一遍前缀异或和。

    然后,我们根据前缀异或和建一棵可持久化(Trie)树。

    接下来最核心的来了:

    我们先求出以每个点为右端点所能得到的最大异或和,这可以在(Trie)树上查询得到(和普通的(Trie)树是一样的)。

    然后,把这些值连同该右端点全扔入大根堆里。

    每次,我们取出堆顶,统计答案后求出以该点为右端点所能得到的次大值,然后重新扔入堆里。如果再取到该右端点,就是次次大值、次次次大值,以此类推。

    那么如何求次大值呢?

    没关系,反正我们本来就是可持久化(Trie)树,直接复制该点的(Trie)树并将求出的最大值所对应的数在树上删去即可。

    这种方法的复杂度应该是(O((n+k)log Max a_i)),但我写得弱了一点,变成了(O((2n+k)log Max a_i))。虽然很好改,但我懒得改了。。。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define RU Reg unsigned
    #define Con const
    #define CI Con int&
    #define CU Con unsigned&
    #define I inline
    #define W while
    #define N 500000
    #define K 200000
    #define mp make_pair
    #define fir first
    #define sec second
    using namespace std;
    int n,k,p[N+5];unsigned a[N+5];typedef pair<unsigned,int> Pr;
    priority_queue<Pr> q;
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    		#undef D
    }F;
    class PersistentTrie//可持久化Trie树
    {
    	private:
    		#define SZ ((N<<1)+K+1)
    		#define Log 33
    		int tot,Rt[N+5];struct node {int Sz,S[2];}O[SZ*Log+5];
    		I void upt(int& rt1,RI rt2,CU x,CI t,CI D)//修改
    		{
    			if((O[rt1=++tot]=O[rt2]).Sz+=t,!~D) return;//复制节点,更新size
    			RI d=(x>>D)&1;upt(O[rt1].S[d],O[rt2].S[d],x,t,D-1);//处理子节点
    		}
    		I unsigned qry(int& rt,CI x,CI D)//询问与x的最大异或和
    		{
    			if(!~D) return 0;RI d=(x>>D)&1;
    			return O[O[rt].S[d^1]].Sz?qry(O[rt].S[d^1],x,D-1)|(1<<D):qry(O[rt].S[d],x,D-1);//能使这一位为1就必使其为1,否则使其为0
    		}
    	public:
    		I PersistentTrie() {tot=1,Update(0,0,0,1);}
    		I void Update(CI v1,CI v2,CU x,CI t) {upt(Rt[v1],Rt[v2],x,t,31);}
    		I unsigned Query(CI v) {RU t=qry(Rt[v],a[v],31);return Update(v,v,a[v]^t,-1),t;}//询问,为避免计算多次贡献将其删去
    }P;
    int main()
    {
    	RI i;Pr t;Reg long long ans=0;
    	for(F.read(n,k),i=1;i<=n;++i) F.read(a[p[i]=i]),a[i]^=a[i-1],P.Update(i,i-1,a[i],1);//初始化建树
    	for(i=1;i<=n;++i) q.push(mp(P.Query(i),i));//询问然后扔入堆中
    	for(i=1;i<=k;++i) t=q.top(),q.pop(),ans+=t.fir,//取出堆顶,统计答案
    		--p[t.sec]&&(q.push(mp(P.Query(t.sec),t.sec)),0);//将次大值扔入堆中
    	return printf("%lld",ans),0;//输出答案
    }
    
  • 相关阅读:
    使用Windows 批处理删除CVS文件
    五种提高 SQL 性能的方法
    读取服务器数据填充Select下拉列表[原创]
    有XMLHTTP实现无刷新功能[原创]
    一些关于流量和带宽的知识
    [转帖] 25个超级经典故事!!!
    用XMLTextReader类加速.NET中XML存取
    ASP.NET中的多重表单[转]
    XML中的二进制文件的编码与解码[原创]
    Asp.net控件命名规范
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5283.html
Copyright © 2020-2023  润新知