zoukankan      html  css  js  c++  java
  • P5283 异或粽子

    https://www.luogu.com.cn/problem/P5283

    其实并不需要可持久化,只需要不同的 trie 就行了
    先把它来个异或前缀和,这样问题就转化为了求前 (k) 大的任意两数异或的和,记得要补一个 (0)
    因为异或有交换律,不妨先求前 (2k) 大的和,然后答案除以二,这样就不用考虑重复的问题了

    然后把每个数插入到 trie 上,这样可以 (O(log a_i)) 的求一个数与这个数列中其他数异或的第 (rank) 大的结果(考虑每一位是向和这个数在那一位相同的数字方向走,还是相异)
    然后开一个堆,首先把每个数和别的数异或的最大结果插入堆中,然后每次取出最大值,假设这是某个数与其他数异或的第 (rk) 大的,那么就答案加上它,并把这个数与其他数异或第 (rk+1) 大的插入对中

    另外手写对跑的真比 stl 的快得多,在不开O2的代码中大概第三左右

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN puts("")
    inline long long read(){
    	register long long x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n,k;
    struct node{
    	int id,rk;
    	long long num;
    }heap[50000006];
    int size;
    struct tr{
    	tr *son[2];
    	int cnt;
    }dizhi[50000006],*root,*null;
    int tot;
    long long a[500006];
    inline void New(tr *&a){
    	a=&dizhi[++tot];
    	a->son[0]=a->son[1]=null;
    }
    #define MAX 33
    void insert(tr *tree,long long num,int pos){
    	tree->cnt++;
    	if(pos<0) return;
    	int nex=(num>>pos)&1;
    	if(tree->son[nex]==null) New(tree->son[nex]);
    	insert(tree->son[nex],num,pos-1);
    }
    long long ask(tr *tree,long long num,int rk,int pos){
    //		printf("rk = %d
    ",rk);
    	if(pos<0) return 0;
    	int nex=((num>>pos)&1)^1;
    	if(tree->son[nex]->cnt>=rk) return (1ll<<pos)+ask(tree->son[nex],num,rk,pos-1);
    	return ask(tree->son[nex^1],num,rk-tree->son[nex]->cnt,pos-1);
    }
    inline int operator >=(const node &a,const node &b){return a.num>=b.num;}
    inline void push(node x){
    	heap[++size]=x;
    	reg int i=size,fa;
    	while(i>1){
    		fa=i>>1;
    		if(heap[fa]>=heap[i]) return;
    		std::swap(heap[fa],heap[i]);i=fa;
    	}
    }
    inline node pop(){
    	node ret=heap[1];heap[1]=heap[size--];
    	reg int i=1,ls,rs;
    	while((i<<1)<=size){
    		ls=i<<1;rs=ls|1;
    		if(rs<=size&&heap[rs]>=heap[ls]) ls=rs;
    		if(heap[i]>=heap[ls]) break;
    		std::swap(heap[i],heap[ls]);i=ls;
    	}
    	return ret;
    }
    int main(){
    	n=read();k=read()*2;
    	null=&dizhi[0];null->son[0]=null->son[1]=null;
    	New(root);
    	insert(root,0,MAX);
    	for(reg int i=1;i<=n;i++){
    		a[i]=read()^a[i-1];
    		insert(root,a[i],MAX);
    	}
    	for(reg int i=0;i<=n;i++) push((node){i,1,ask(root,a[i],1,MAX)});
    	reg node now;long long ans=0;
    	while(k--){
    		now=pop();
    		ans+=now.num;
    		if(now.rk<n) push((node){now.id,now.rk+1,ask(root,a[now.id],now.rk+1,MAX)});
    	}
    	printf("%lld",ans>>1);
    	return 0;
    }
    
  • 相关阅读:
    二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment
    思维题 HDOJ 5288 OO’s Sequence
    树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland
    最大流增广路(KM算法) HDOJ 1853 Cyclic Tour
    最大流增广路(KM算法) HDOJ 1533 Going Home
    最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱
    Complete the Word CodeForces
    Gadgets for dollars and pounds CodeForces
    Vasya and Basketball CodeForces
    Carries SCU
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/13817021.html
Copyright © 2011-2022 走看看