码迷,mamicode.com
首页 > 其他好文 > 详细

P4735 最大异或和

时间:2019-03-05 21:44:25      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:节点   etc   cst   类型   org   void   last   ==   ase   

题目链接

题目描述

给定一个非负整数序列{a},初始长度为N。

有M个操作,有以下两种操作类型:

A x:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。

Q l r x:询问操作,你需要找到一个位置p,满足l≤p≤r,使得: a[p]⊕a[p+1]⊕...⊕a[N]⊕x 最大,输出最大是多少。

输入输出格式

输入格式:

第一行包含两个整数N,M,含义如问题描述所示。
第二行包含 N个非负整数,表示初始的序列A
接下来 M行,每行描述一个操作,格式如题面所述。

输出格式:

假设询问操作有 T 个,则输出应该有 T 行,每行一个整数表示询问的答案。

输入输出样例

输入样例#1: 
5  5
2  6 4 3 6
A 1 
Q 3 5 4 
A 4
Q 5 7 0 
Q 3 6 6 
输出样例#1: 
4
5
6
关于这道题思路就不再多说,主要讲一下细节问题。
技术图片
  1 #include<iostream>
  2 #include<string>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<map>
  7 #include<algorithm>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 #define maxn 600005
 12 using namespace std;
 13 
 14 inline int read()
 15 {
 16     int x=1,res=0;
 17     char c=getchar();
 18     while(c<0||c>9)
 19     {
 20         if(c==-)
 21         x=-1;
 22         c=getchar();
 23     }
 24     while(c>=0&&c<=9)
 25     {
 26         res=res*10+(c-0);
 27         c=getchar();
 28     }
 29     return res*x;
 30 }
 31 
 32 int n,m,tot,aa;
 33 int last[maxn*24],root[maxn],s[maxn];
 34 int tree[maxn*24][2];
 35 
 36 void trie(int i,int k,int l,int r)
 37 {
 38     if(k<0)
 39     {
 40         last[r]=i;
 41         return;
 42     }
 43     int c=(s[i]>>k)&1;
 44     if(l) tree[r][c^1]=tree[l][c^1];
 45     tree[r][c]=++tot;
 46     trie(i,k-1,tree[l][c],tree[r][c]);
 47     last[r]=max(last[tree[r][0]],last[tree[r][1]]);
 48 }
 49 
 50 int ask(int now,int val,int k,int l)
 51 {
 52     if(k<0) return val^s[last[now]];
 53     int c=val>>k&1;
 54     if(last[tree[now][c^1]]>=l)/*如果以这个点为根的子树上的结点的最大编号 
 55     大于等于l,那么这个结点就有意义,否则,这个结点就没有任何意义*/
 56     {
 57         return ask(tree[now][c^1],val,k-1,l);
 58     }
 59     else
 60     {
 61         return ask(tree[now][c],val,k-1,l);
 62     }
 63 }
 64 
 65 int main()
 66 {
 67     n=read();m=read();
 68     last[0]=-100;/*0号点其实就是trie树上不存在的点,之所以清为负数而不是
 69     0,这是因为如果询问的区间的l是1,那么根据我们会把所有last的值>=0(l-1)
 70     的数计算进去,这样如果不清为负数,那么trie树上没有的点我们也会错误的
 71     计算进去,所以last一定要清为负数。 
 72     */
 73     root[0]=++tot;/*这个根节点标记为1是为了和不在trie树上的点区分开 */ 
 74     trie(0,23,0,1);//先构造一个全0的trie树 
 75     for(int i=1;i<=n;i++)
 76     {
 77         aa=read();
 78         s[i]=s[i-1]^aa;
 79         root[i]=++tot;
 80         trie(i,23,root[i-1],root[i]);
 81     }
 82     for(int i=1;i<=m;i++)
 83     {
 84         char c;
 85         scanf("%s",&c);
 86         if(c==A)
 87         {
 88             aa=read();
 89             root[++n]=++tot;
 90             s[n]=s[n-1]^aa;
 91             trie(n,23,root[n-1],root[n]);
 92         }
 93         else
 94         {
 95             int l,r,x;
 96             l=read();r=read();x=read();
 97             printf("%d\n",ask(root[r-1],s[n]^x,23,l-1));
 98         }
 99     }
100 }
View Code

 


P4735 最大异或和

标签:节点   etc   cst   类型   org   void   last   ==   ase   

原文地址:https://www.cnblogs.com/snowy2002/p/10479564.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!