zoukankan      html  css  js  c++  java
  • 【洛谷 P4735】 最大异或和 (可持久化Trie)

    题目链接
    维护整个数列的异或前缀和和(s),然后每次就是要求(s[N] ext{^}x ext{^}s[k],l-1<=k<=r-1)的最大值
    如果没有(l)的限制,那么直接用可持久化(Trie)查询第(r)个版本跑最大异或和就行。
    (Trie)求最大异或值的方法就是把数看成二进制建树,一位位往下走能往相反的就往相反的走,不能就走相同的,走到底就是答案。
    现在多了(l)的限制,所以需要记录每个节点在这个节点的子树中结尾的数的最大的编号是多少,记为(latest),每次限制只能走(latest>=l-1)的节点。

    #include <cstdio>
    #define re register
    const int MAXN = 20000010;
    inline int read(){
        int s = 0, w = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
        return s * w;
    }
    int trie[MAXN][2], latest[MAXN], root[MAXN], s[MAXN];
    int n, m, num;
    inline int max(const int a, const int b){
    	return a > b ? a : b;
    }
    void insert(int i, int k, int p, int q){
    	if(k < 0){ latest[q] = i; return ; }
    	re int c = s[i] >> k & 1;
    	if(p) trie[q][c ^ 1] = trie[p][c ^ 1];
    	trie[q][c] = ++num;
    	insert(i, k - 1, trie[p][c], trie[q][c]);
    	latest[q] = max(latest[trie[q][0]], latest[trie[q][1]]);
    }
    int query(int now, int val, int k, int limit){
    	if(k < 0) return s[latest[now]] ^ val;
    	re int c = val >> k & 1;
    	if(latest[trie[now][c ^ 1]] >= limit) return query(trie[now][c ^ 1], val, k - 1, limit);
    	return query(trie[now][c], val, k - 1, limit);
    }
    char opt;
    int main(){
    	n = read(); m = read();
    	root[0] = ++num; latest[0] = -1;
    	insert(0, 23, 0, root[0]);
    	for(re int i = 1; i <= n; ++i){
    	   s[i] = s[i - 1] ^ read();
    	   root[i] = ++num;
    	   insert(i, 23, root[i - 1], root[i]);
        }
        for(re int i = 1, l, r, x; i <= m; ++i){
           do opt = getchar(); while(opt != 'A' && opt != 'Q');
           if(opt == 'A'){
           	 x = read();
           	 root[++n] = ++num;
           	 s[n] = s[n - 1] ^ x;
           	 insert(n, 23, root[n - 1], root[n]);
           }
           else{
           	 l = read(); r = read(); x = read();
           	 printf("%d
    ", query(root[r - 1], s[n] ^ x, 23, l - 1));
           }
        }
        return 0;
    }
    
  • 相关阅读:
    Spring Security demo
    applicationContext-XXX.xml和XXX-servlet.xml的区别
    搜索意图识别浅析
    如何配置使用Dnsmasq
    机器学习十大算法之EM算法
    如何利用OpenSSL生成证书
    11月13日晚直播预告 | 关于数据可视化,网易大数据资深专家将在这里告诉你
    漫话中文分词
    10分钟快速构建汽车零售看板
    聊一聊整车厂的那些事——售后配件业务
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10315450.html
Copyright © 2011-2022 走看看