codechef Xor Queries (可持久化字典树)

题目链接:codechef Xor Queries

题意:

题解:

一棵可持久化字典树就行了。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3 using namespace std;
 4
 5 const int N=5e5+7;
 6 struct Node{int son[2],cnt;}ch[N*40];
 7 int root[N],cnt,ed,n;
 8
 9 void ins(int &x,int y,int v,int i=20)
10 {
11     ch[x=++cnt]=ch[y],ch[x].cnt++;
12     if(i<0)return;
13     int now=(v>>i)&1;
14     ins(ch[x].son[now],ch[y].son[now],v,i-1);
15 }
16
17 int ask_xor(int x,int y,int v,int i=20,int ans=0)
18 {
19     if(i<0)return ans;
20     int now=(v>>i)&1;
21     if(ch[ch[y].son[now^1]].cnt-ch[ch[x].son[now^1]].cnt>0)
22         return ask_xor(ch[x].son[now^1],ch[y].son[now^1],v,i-1,ans+((now^1)<<i));
23     else return ask_xor(ch[x].son[now],ch[y].son[now],v,i-1,ans+(now<<i));
24 }
25
26 int ask_num(int x,int y,int v,int i=20,int ans=0)
27 {
28     if(i<0)return ans+ch[y].cnt-ch[x].cnt;
29     int now=(v>>i)&1,tmp=0;
30     if(now)tmp+=ch[ch[y].son[0]].cnt-ch[ch[x].son[0]].cnt;
31     return ask_num(ch[x].son[now],ch[y].son[now],v,i-1,ans+tmp);
32 }
33
34 int kth(int x,int y,int v,int i=20,int ans=0)
35 {
36     if(i<0)return ans;
37     int tmp=ch[ch[y].son[0]].cnt-ch[ch[x].son[0]].cnt;
38     if(tmp>=v)return kth(ch[x].son[0],ch[y].son[0],v,i-1,ans);
39     else return kth(ch[x].son[1],ch[y].son[1],v-tmp,i-1,ans+(1<<i));
40 }
41
42 int main(){
43     scanf("%d",&n);
44     while(n--)
45     {
46         int l,r,x;
47         scanf("%d",&x);
48         if(x==0)
49         {
50             scanf("%d",&x),ed++;
51             ins(root[ed],root[ed-1],x);
52         }
53         else if(x==1)
54         {
55             scanf("%d%d%d",&l,&r,&x);
56             printf("%d\n",ask_xor(root[l-1],root[r],x));
57         }
58         else if(x==2)
59         {
60             scanf("%d",&x);
61             ed-=x,cnt=root[ed+1];
62         }
63         else if(x==3)
64         {
65             scanf("%d%d%d",&l,&r,&x);
66             printf("%d\n",ask_num(root[l-1],root[r],x));
67         }
68         else
69         {
70             scanf("%d%d%d",&l,&r,&x);
71             printf("%d\n",kth(root[l-1],root[r],x));
72         }
73     }
74     return 0;
75 }

时间: 2024-10-31 06:27:14

codechef Xor Queries (可持久化字典树)的相关文章

Hdu-4757 Tree(可持久化字典树+lca)

题目链接:点这 我的github地址:点这 Problem Description Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will giv

【HDU 6191】Query on A Tree 【可持久化字典树】

题目 给出一棵有n个结点的树,树根是1,每个结点给出一个value.然后给出q个询问,每个询问给出两个整数u和x,你要在以u结点为根的子树中找出一个结点v,使得val[v] xor x最大, 并输出这个最大值 分析 显而易见的可持久化字典树,只不过这次每次查询不是查询一个区间,而是查询一棵子树.那么也很简单,我们只要预处理出dfs序然后找出每个结点以它为根的子树在dfs序中的区间.然后以这个区间建可持久化字典树就可以了. 1 #include <cstdio> 2 #include <c

2014百度之星资格赛—— Xor Sum(01字典树)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起

【BZOJ2741】【FOTILE模拟赛】L 可持久化字典树+分块

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44496739"); } 题解: 首先我们处理出来sum[0,n]作为异或前缀和,然后答案就不再是[l,r]中间某段区间的异或和,而转化成求了[l?1,r]中任意两点异或和的最大值. 然后我们分块处理出fi,j表示 [第i块的开头,j

hdu 4757 Tree(可持久化字典树)

题目链接:hdu 4757 Tree 题目大意:给定一棵树,每一个节点有一个值.如今有Q次询问,每次询问u到v路径上节点值与w亦或值的最大值. 解题思路:刚開始以为是树链剖分,事实上树链剖分仅仅是用来求LCA(能够不用树链剖分). 可持久化字典树.在每次插入的同一时候,不改动原先的节点.而是对全部改动的节点复制一个新的节点,而且在新的节点 上做操作,这样做的目的是可以获取某次改动前的状态.同过可持久化的操作,保留了改动前后的公共数据. 对给定树上的全部节点权值建立01字典树,然后每一个节点都保存

Codeforces 706D Vasiliy&#39;s Multiset(可持久化字典树)

[题目链接] http://codeforces.com/problemset/problem/706/D [题目大意] 要求实现一个集合中的三个操作,1:在集合中加入一个元素x,2:从集合中删除一个元素x(保证x存在),3:要求从集合中选出一个数,使得其与给出的数x的异或值最大,输出这个异或值. [题解] 可以将所有的以二进制形式存在01字典树上,删除即插入权值为-1的二进制串,对于异或值最大的操作,我们只要在字典树上按位贪心,从最高位开始尽量保证该位存在最后就能得到答案.写代码的时候直接写了

hdu 6191 Query on A Tree(dfs序+可持久化字典树)

题目链接:hdu 6191 Query on A Tree 题意: 给你一棵树,每个节点有一个值,现在有q个询问,每个询问 询问一个u x,问以u为根的子树中,找一个节点,使得这个节点的值与x异或的值最大,输出那个最大的值. 题解: dfs序和一棵可持久化字典树就搞定了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4

bzoj3166: [Heoi2013]Alo 可持久化字典树

左右两边的比i大的最近的两个值.然后可持久化字典树即可. #include<bits/stdc++.h> using namespace std; int maxn=0,n,root[1600000],a[50010],cnt=0,l[1600000],r[1600000],p1[50010][25],p2[50010][25],sum[1600000],ans=0,pans=0,l1[50010],r1[50010],l2[50010],r2[50010]; void add(int &am

Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树

Xors on Segments 转换一下变成询问区间选两个数异或的最大值, 要注意的是一个数作为左端点要-1, 所以在回滚莫队的时候用两棵字典树维护. 这个题居然n ^ 2 也能过...  其实用分治 + 可持久化字典树可以做到n * log(n) * log(n), 懒得写了... #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #defin