bzoj3261: 最大异或和 可持久化trie

题意:给定一个非负整数序列{a},初始长度为N。
有M个操作,有以下两种操作类型:
1、Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
2、Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。
题解:可持久化trie
用前缀异或来建树,查询就变成了last^x和l到r中a【p】异或最大值是多少
先插入一个0,然后像可持久化线段树那样建树即可,还是挺简单的

/**************************************************************
    Problem: 3261
    User: walfy
    Language: C++
    Result: Accepted
    Time:4584 ms
    Memory:179416 kb
****************************************************************/

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=600000+10,maxn=100000+10,inf=0x3f3f3f3f;

struct trie{
    int sz,cnt,root[N],ch[N*25][2],num[N*25];
    void init()
    {
        sz=cnt=0;
        root[++sz]=++cnt;
        int now=root[sz];
        for(int i=24;i>=0;i--)
        {
            ch[now][0]=++cnt;
            now=ch[now][0];
            num[now]++;
        }
    }
    void add(int x)
    {
        root[++sz]=++cnt;
        int now=root[sz],last=root[sz-1];
        for(int i=24;i>=0;i--)
        {
            ch[now][(x>>i)&1]=++cnt;
            ch[now][!((x>>i)&1)]=ch[last][!((x>>i)&1)];
            now=ch[now][(x>>i)&1];
            num[now]=num[ch[last][(x>>i)&1]]+1;
            last=ch[last][(x>>i)&1];
        }
    }
    void query(int l,int r,int x)
    {
        int now=root[r],last=root[l],ans=0;
        for(int i=24;i>=0;i--)
        {
//            if(now==128)printf("%d %d %d %d\n",now,last,num[ch[now][!((x>>i)&1)]],num[ch[last][!((x>>i)&1)]]);
            if(num[ch[now][!((x>>i)&1)]]>num[ch[last][!((x>>i)&1)]])
            {
                now=ch[now][!((x>>i)&1)];
                last=ch[last][!((x>>i)&1)];
                ans+=(1<<i);
//                printf("%d %d\n",now,0);
            }
            else
            {
                now=ch[now][(x>>i)&1];//,printf("%d %d\n",now,1);
                last=ch[last][(x>>i)&1];
            }
//            printf("%d--\n",now);
        }
        printf("%d\n",ans);
    }
    void debug(int now)
    {
        printf("%d %d %d %d\n",now,num[now],ch[now][0],ch[now][1]);
        if(ch[now][0])debug(ch[now][0]);
        if(ch[now][1])debug(ch[now][1]);
    }
}tree;
int main()
{
    int n,m,sum=0;
    scanf("%d%d",&n,&m);
    tree.init();
    for(int i=1;i<=n;i++)
    {
        int a;scanf("%d",&a);
        a^=sum;sum=a;tree.add(a);
//        printf("%d---\n",a);
    }
    while(m--)
    {
        char op[5];scanf("%s",&op);
        if(op[0]=='A')
        {
            int x;scanf("%d",&x);
            x^=sum;sum=x;tree.add(x);
//            printf("%d---\n",x);
        }
        else
        {
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            x^=sum;tree.query(l-1,r,x);
//            printf("%d+++\n",x);
        }
    }
//    tree.debug(tree.root[2]);
    return 0;
}
/*****************
5  5
2  6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
*****************/

原文地址:https://www.cnblogs.com/acjiumeng/p/9729012.html

时间: 2024-10-10 02:15:36

bzoj3261: 最大异或和 可持久化trie的相关文章

[bzoj3261]最大异或和[可持久化trie树]

因为要求异或和最大,所以可以考虑从高位开始,向低位枚举尽可能接近~x的值,所以以二进制位为关键字,建立可持久化trie树,根据异或和的性质,XOR_SUM{i,j}=XOR_SUM{1,j} xor XOR_SUM{1,i-1},所以查询问题也可以解决了. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <c

[Luogu P4735]最大异或和(可持久化Trie)

[Luogu P4735]最大异或和(可持久化Trie) 题面 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 分析 维护\(sum[i]=sum[i-1] \ \text{XOR} \ a[i]\),那么答案就是\(sum[

BZOJ 3261: 最大异或和 [可持久化Trie]

3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1513  Solved: 657[Submit][Status][Discuss] Description 给定一个非负整数序列 {a},初始长度为 N.       有   M个操作,有以下两种操作类型: 1 .A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2 .Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得: a[p]

【bzoj3281】最大异或和 可持久化Trie树

题目描述 给定一个非负整数序列 {a},初始长度为 N.       有M个操作,有以下两种操作类型:1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2.Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 输入 第一行包含两个整数 N  ,M,含义如问题描述所示.   第二行包含 N个非负整数,表示初始的序列 A . 接下来 M行,每行描述一个

【BZOJ4103】[Thu Summer Camp 2015]异或运算 可持久化Trie树

[BZOJ4103][Thu Summer Camp 2015]异或运算 Description 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor  yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij. Input 第一行包含两个正整数n,m,分别表示两个数列的长度 第二行包含n个非负整数xi 第三行包含m个非负整数yj 第四行包含一个正整数p,表示询问次数 随后p行,每行

bzoj4103异或运算 可持久化trie树

要去清华冬令营了,没找到2016年的题,就先坐一坐15年的. 因为n很小,就按照b串建可持久化trie树,a串暴力枚举. 其他的直接看代码. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1,ch=getchar(); while(ch<'0'||ch

BZOJ 3261 最大异或和 可持久化Trie树

题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们可以维护前缀和 然后就是使x^sum[n]^sum[p-1]最大 x^sum[n]为定值,于是用Trie树贪心即可 考虑到l-1<=p-1<=r-1,我们不能对于每个询问都建一棵Trie树,但是我们可以对于Trie数维护前缀和,建立可持久化Trie树 每个区间[l,r]的Trie树为tree[r]-tree[l-1]

bzoj4103[Thu Summer Camp 2015]异或运算(可持久化trie树)

一看数据范围,n很小m很大,对长的那一维建可持久化线段树,另一维暴力枚举 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,tot,p; 7 int rt[300005]; 8 int x[2005]; 9 int y[300005]; 10 struct Trie{ 11 in

P4592 [TJOI2018]异或 (可持久化Trie)

[题目链接] https://www.luogu.org/problemnew/show/P4592 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: \(1\;x\;y:\)查询节点xx的子树中与\(y\)异或结果的最大值 \(2\;x\;y\;z:\)查询路径\(x\)到\(y\)上点与\(z\)异或结果最大值 打挂代码 题解代码 原文地址:https://www.cnblogs.com/liz