01字典树(删除与添加操作)

风流意气都作罢 提交于 2020-02-28 04:33:59

http://acm.hdu.edu.cn/showproblem.php?pid=5536

题意:在一个数组中找出 (s[i]+s[j])^s[k] 最大的值,其中 i、j、k 各不相同。

题解:1、可直接暴力O(n3

2、01字典树可以在数组中找到一个数与X异或和最大和其异或结果。本题中的X是数组中的两个不同的数的和,在数组中找另一个与前两个数不同的异或和最大。为了确保找到数与前两个数不同,所有要进行删除与添加操作。另开一个数组记录节点访问次数,通过对访问次数的加减进行删除与添加操作。

 https://blog.csdn.net/zuzhiang/article/details/79872805

#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
using namespace std;
typedef unsigned long long ll ;
int tree[32*1009][2] , vis[32*1009] , num[32*1009];
int a[1009];
int tol ;

void insert(int x )
{
    int u = 0 ;
    for(int i = 31 ; i >= 0 ; i--)
    {
        int p = (x >> i)&1;
        if(!tree[u][p]) tree[u][p] = ++ tol ;
        u = tree[u][p];
        num[u]++;
    }
    vis[u] = x ;
}

void update(int x , int add)
{
    int u = 0 ;
    for(int i = 31 ; i >= 0 ; i--)
    {
        int p = (x >> i) & 1 ;
        u = tree[u][p];
        num[u] += add;
    }
}

int research(int x)
{
    int u = 0 ;
    for(int i = 31  ; i >= 0 ; i--)
    {
        int p = (x >> i) & 1 ;
        if(tree[u][p^1] && num[tree[u][p^1]]) u = tree[u][p^1];
        else u = tree[u][p];
    }
    return x ^ vis[u];
}

void init()
{
    memset(vis, 0 , sizeof(vis));
    memset(tree , 0 , sizeof(tree));
    memset(num , 0 , sizeof(num));
    tol = 0 ;
}
int main()
{
    int t ;
    scanf("%d" , &t);
    while(t--)
    {
        init();
        int n ;
        scanf("%d" , &n);
        for(int i = 0 ; i < n ; i++)
        {
            scanf("%d" , &a[i]);
            insert(a[i]);
        }
        int ma = -INF ;
        for(int i = 0 ; i < n ; i++)
        {
            for(int j = i + 1 ; j < n ; j++)
            {
                update(a[i] , -1);
                update(a[j] , -1);
                ma = max(ma , research(a[i]+a[j]));
                update(a[i] , 1);
                update(a[j] , 1);
            }
        }
        cout << ma << endl ;
    }
    return 0;
}

 

 

maxi,j,k(si+sj)sk
maxi,j,k(si+sj)sk
maxi,j,k(si+sj)sk
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!