您的位置:首页 > 产品设计 > UI/UE

CodeChef XRQRS - Xor Queries

2017-01-23 19:59 483 查看
CodeChef XRQRS - Vjudge

题目简述
给出一个一维数组和若干个不同类型的询问:
• 0 x :在数组的最后添加 x
• 1 L R x :在区间 [L,R] 中找到 y,使 x xor y 最大
• 2 k :删除数组的最后 k 个数
• 3 L R x :统计区间 [L,R] 中有多少个数 y 小于或等于 x
• 4 L R k :找出区间 [L,R] 中从小到大的第 k 个数

题解

将每一个数按照其二进制插入 TRIE 中,维护前缀的 TRIE 树总和。

对于每一个询问,在两棵TRIE 上由上至下的走就可以了。

#include<iostream>
#include<cstdio>
#include<cstring>

#define ll long long
using namespace std;
const int N = 500000 + 10;
int rt
;
int siz
,son
[2];
int tot;
int m;
int n;
void change(int &x, int xx, int d, int p){
x = ++tot;
memcpy(son[x], son[xx], sizeof(son[x]));
siz[x] = siz[xx] + 1;
if(d < 0)
return ;
if((p >> d-1) & 1)
change(son[x][1], son[xx][1], d-1, p);
else
change(son[x][0], son[xx][0], d-1, p);
}
int query1(int x, int xx, int d, int y){
if(d < 0)
return 0;
bool z = (y >> d-1) & 1 ^ 1;
if(siz[son[xx][z]] - siz[son[x][z]])
return (1 << d-1) + query1(son[x][z], son[xx][z], d-1, y);
else
return query1(son[x][z^1], son[xx][z^1], d-1, y);
}
int query2(int x, int xx, int d, int now, int y){
if(d<0)
return 0;
if(y >= now + (1 << d-1))
return siz[son[xx][0]] - siz[son[x][0]] + query2(son[x][1], son[xx][1], d-1, now+(1 << d-1), y);
else
return query2(son[x][0], son[xx][0], d-1, now, y);
}
int query3(int x,int xx,int d,int k){
if(d < 0)
return 0;
int t = siz[son[xx][0]] - siz[son[x][0]];
if(k <= t)
return query3(son[x][0], son[xx][0], d-1, k);
else
return (1 << d-1) + query3(son[x][1], son[xx][1], d-1, k-t);
}
int main(){
int o, x, y, z;
scanf("%d", &m);
while(m--){
scanf("%d", &o);
if(o == 0){
scanf("%d", &x);
change(rt[++n], rt
, 19 ,x);
}
if(o == 1){
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",z^query1(rt[x-1],rt[y],19,z));
}
if(o == 2){
scanf("%d", &x);
n -= x;
tot = rt[n+1] - 1;
}
if(o == 3){
scanf("%d%d%d", &x, &y, &z);
printf("%d\n", query2(rt[x-1], rt[y], 19, 0, z));
}
if(o == 4){
scanf("%d%d%d", &x,&y,&z);
printf("%d\n", query3(rt[x-1], rt[y], 19, z));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: