ACdream - 1063 平衡树(01字典树)

点我看题

题意:三个操作insert qmin qmax,利用某种数据结构,求y^x最大或最小,其中y为询问的时候给出的,x为insert进去的.

分析:利用字典数将insert进去的数存起来,字典树从根的儿子结点到最后的叶子结点依次存放数据的二进制高位到低位,然后查询.对于x^y最大值的查询,当然要看有没有与y当前位不同的,而最小值就看有没有与当前位相反的...

参考代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int inf = 0x3f3f3f3f;
const int maxn = 1e4;
int n;
//TrieTree
int tt[320000][2];
int node;//结点个数

void init()
{
    mem(tt[0],0);
    node = 1;
}

void Insert( int num)
{
    int rt = 0;
    for( int i = 30; i >= 0; i--)//2^31>1e9
    {
        int id = ((1<<i)&num)>>i;//求出num的第i位是1还是0
        if( !tt[rt][id])//结点不存在,新建一个
        {
            mem(tt[node],0);
            tt[rt][id] = node++;
        }
        rt = tt[rt][id];
    }
}

//求最小值
int QueryMin( int num)
{
    int rt = 0;
    int ans = 0;
    for( int i = 30; i >= 0; i--)
    {
        int id = ((1<<i)&num)>>i;
        if( tt[rt][id])//相同的存在
            rt = tt[rt][id];
        else
        {
            ans += (1<<i);
            rt = tt[rt][1-id];
        }
    }
    return ans;
}

//求最大值
int QueryMax( int num)
{
    int rt = 0;
    int ans = 0;
    for( int i = 30; i >= 0; i--)
    {
        int id = ((1<<i)&num)>>i;
        if( tt[rt][1-id])//相反的存在
        {
            ans += (1<<i);
            rt = tt[rt][1-id];
        }
        else
            rt = tt[rt][id];
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while( T--)
    {
        init();
        scanf("%d",&n);
        while( n--)
        {
            char op[10];
            int num;
            scanf("%s%d",op,&num);
            if( !strcmp(op,"insert"))
                Insert(num);
            else if( !strcmp(op,"qmin"))
                printf("%d\n",QueryMin(num));
            else if( !strcmp(op,"qmax"))
                printf("%d\n",QueryMax(num));
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值