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


    前言

    去年打酱油的时候,我还不会字典树= =

    貌似我( equire{enclose}enclose{horizontalstrike}{O(n^2logn)})的分都没拿满?

    题目

    洛谷

    讲解

    异或?l~r的连续区间?

    明显可以前缀和优化

    接下来就变成了求前(k)大的点对异或值了

    看题解得知,这种类型的问题可以这么解决:

    先把所有的前缀和插入进一棵字典树中,注意要插入0

    此字典树需要记录的信息有:

    1.两个儿子(常规操作)

    2.子树大小(记录这条路走下去可以最多选出多少个数)

    然后我们可以将每一个前缀和的查询的最大值插进优先队列

    每次取出最大的一个,累加答案,然后求出次大的值,放回优先队列...

    循环做(k)次,就完事了

    吗?

    NO!由于(s_i oplus s_j=s_j oplus s_i),所以每个较大值会出现两次,我们要将(2k)个较大数累加起来,最后将答案除以二即可

    时间复杂度为(O(nlog_2n))

    注意开(long long)

    代码

    //12252024832524
    #include <queue>
    #include <cstdio>
    #include <algorithm>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 500005;
    const int MAXLOG = 32;
    int n,k;
    LL s[MAXN],ans;
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    void Put1(LL x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    void Put(LL x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x);
    	if(c >= 0) putchar(c);
    }
    template <typename T>T Max(T x,T y){return x > y ? x : y;}
    template <typename T>T Min(T x,T y){return x < y ? x : y;}
    template <typename T>T Abs(T x){return x < 0 ? -x : x;}
    
    struct Node
    {
    	int ID,rk;
    	LL val;
    	Node(){}
    	Node(int ID1,int rk1,LL val1){
    		ID = ID1;
    		rk = rk1;
    		val = val1;
    	}
    	bool operator < (const Node &px) const{
    		return val < px.val;
    	}
    };
    priority_queue<Node> q;
    
    int tot;
    struct node
    {
    	int ch[2],siz;
    }t[MAXN * MAXLOG];
    void ins(LL x)
    {
    	int now = 0;
    	for(int i = MAXLOG - 1;i >= 0;-- i)
    	{
    		bool ID = x >> i & 1;
    		if(!t[now].ch[ID]) t[now].ch[ID] = ++tot;
    		now = t[now].ch[ID];
    		t[now].siz++;
    	}
    }
    LL query(int rk,LL w)
    {
    	int now = 0;
    	LL ret = 0;
    	for(int i = MAXLOG - 1;i >= 0;-- i)
    	{
    		bool ID = w >> i & 1,to = ID ^ 1;
    		if(t[now].ch[to]) 
    		{
    			if(t[t[now].ch[to]].siz >= rk) now = t[now].ch[to],ret += 1ll << i;
    			else rk -= t[t[now].ch[to]].siz,now = t[now].ch[ID];
    		}
    		else now = t[now].ch[ID];
    	}
    	return ret;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); k = Read() << 1;
    	for(int i = 1;i <= n;++ i) s[i] = Read() ^ s[i-1];
    	for(int i = 0;i <= n;++ i) ins(s[i]);
    	for(int i = 0;i <= n;++ i) q.push(Node(i,1,query(1,s[i])));
    	while(k--)
    	{
    		Node g = q.top(); q.pop(); ans += g.val;
    		if(g.rk < n) q.push(Node(g.ID,g.rk+1,query(g.rk+1,s[g.ID])));
    	}
    	Put(ans >> 1);
    	return 0;
    }
    
  • 相关阅读:
    leetcode66 plusOne
    park/unpark 阻塞与唤醒线程
    leetcode55 jumpGame贪心算法
    ACID特性与事务的隔离级别
    PCB ODB++(Gerber)图形绘制实现方法
    PCB 所建不凡 AWS 技术峰会2018 • 深圳站 2018.9.20
    PCB SQL SERVER 位运算应用实例
    PCB SQL SERVER 枚举分割函数(枚举值分解函数)
    PCB SQL SERVER 正则应用实例
    PCB Genesis 外形加内角孔实现方法
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13392000.html
Copyright © 2020-2023  润新知