1. 程式人生 > >CSU_1216(異或最大值)

CSU_1216(異或最大值)

題目簡述:
經典題目,求一個數組中兩個數異或運算的最大值。題目極其簡單,但是要求的複雜度需要達到O(N * log(N)),還是比較難的。

解題思路:
總的思路就是構建一棵0-1字典樹,然後一個數讓查詢一個與其異或結果最大的數的效率達到O(log(N)),這裡因為異或的特殊性質,可以使用貪心法則來實現。
1、0-1字典樹:
這裡其實是就是二叉樹,之所以叫做字典樹是因為我們的演算法把一個數當成了一個31位的字串來看,比如1就是三十個零外加一個一,這一部分還是比較簡單的。
2、貪心找最大異或值:
異或運算有一個性質,就是對應位不一樣為1,我們要讓結果最大化,就要讓越高的位置為1。我們找跟一個數的異或結果最大的數,就從樹的根結點(最高位)開始找,如果對應位置這個數是0,優先去找那一位為1的數,找不到才去找0;如果對應位置這個數是1,優先去找那一位為0的數,找不到才去找0;最終找到的數就是跟這個數異或結果最大的數。n個數,每個數找一個這樣的數並算出結果求其中的最大值,可以得到答案。

程式碼:

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

using namespace std;

int n,a[100005],tmp[35];
struct node{
    int val;
    node *left, *right;
    node(int value=-1){
        val = value;
        left = right = NULL;
    }
};
node *head = NULL;

void cal(int
num){ memset(tmp,0,sizeof(tmp)); int cnt=0; while(num){ tmp[cnt++]=num%2; num/=2; } for(int i=0;i<15;i++) swap(tmp[i],tmp[30-i]); } void insert(node* &head, int index, int &num){ if(index+1==31){ head->val = num; return; } if
(tmp[index+1]==0 && !head->left) head->left = new node(-1); if(tmp[index+1]==1 && !head->right) head->right = new node(-1); if(tmp[index+1]==0) insert(head->left,index+1,num); if(tmp[index+1]==1) insert(head->right,index+1,num); } int dfs(node* &head,int index){ if(index+1==31) return head->val; if(tmp[index+1]==0){ if(head->right){ return dfs(head->right,index+1); }else{ return dfs(head->left,index+1); } }else{ if(head->left){ return dfs(head->left,index+1); }else{ return dfs(head->right,index+1); } } } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d",&a[i]); head = new node(-1); for(int i=0;i<n;i++) { cal(a[i]); insert(head,-1,a[i]); } int ans=0; for(int i=0;i<n;i++) { cal(a[i]); ans = max(ans, a[i]^dfs(head,-1)); } printf("%d\n",ans); } return 0; }

總結:
簡單的資料結構用得好可以做很多很奇妙的事情,貪心不能忘啊!

相關推薦

CSU_1216

題目簡述: 經典題目,求一個數組中兩個數異或運算的最大值。題目極其簡單,但是要求的複雜度需要達到O(N * log(N)),還是比較難的。 解題思路: 總的思路就是構建一棵0-1字典樹,然後一個數讓查詢一個與其異或結果最大的數的效率達到O(log(N)

01字典樹專題 解決問題不斷更新ing~

以前一直以為字典樹沒有多少用,但是最近一直碰到(難道是以前刷題太少的原因麼),其中有一類問題叫做01字典樹問題,它是用來解決xor的有力武器,通常是給你一個數組,問你一段連續的異或和最大是多少,正常思路貪心dp啥的都會一頭霧水,但是用01字典樹就能很快的解決,實現起來也十分

01字典樹

#include<bits/stdc++.h> using namespace std; const int maxn = 100000 + 5; //集合中的數字個數 typedef long long LL; int ch[32 * maxn

Chip Factory 字典樹求異

  John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor

Chip Factory01字典樹求異

題目描述 John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every p

[二進制trie][貪心]CSUOJ1216

include 貪心 targe printf IV 左右 class using ace 題目傳送門 過了好久,終於重新開始寫博客了。。。 這是一道二進制trie樹的模板題。 二進制trie樹,理解一下就是一顆二叉樹,左右兒子為0或1。 然後每插入一個數就進行一次

pre tmp 數字 markdown %d getchar using 整數 getch 1、1216: 異或最大值 http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1216 Time Limit: 2 Sec Me

中國石油大學 Chip Factory(字典樹處理)

9264: Chip Factory 時間限制: 5 Sec  記憶體限制: 128 MB 提交: 268  解決: 61 [提交] [狀態] [討論版] [命題人:admin] 題目描述 John is a manager of a CPU chip factory,

MQTT的Payload負載的是多少?

我們在學習使用MQTT協議的時候,有的時候我們需要通過MQTT進行一些二進位制的傳送,那麼請問MQTT進行二進位制的傳送的時候,最大支援多少個位元組? 網上答案五花八門,有說64kb的,有說16kb的,有說256kb,有說256M的, 那麼到底是多少呢? 其實答案很簡單,就是268

中國石油大學 Chip Factory(字典樹處理)

9264: Chip Factory 時間限制: 5 Sec  記憶體限制: 128 MB 提交: 268  解決: 61 [提交] [狀態] [討論版] [命題人:admin] 題目描述 John is a

[cqbzoj]區間

奶牛異或 時間限制: 1 Sec 記憶體限制: 64 MB 題目描述 農民約翰在餵奶牛的時候被另一個問題卡住了。他的所有N(1 <= N <= 100,000)個奶牛在他面前排成一行(按序號1..N的順序),按照它們的社會等級排序。奶牛#

二進位制trie樹解問題

trie樹一般可以用於查詢與指定值最近的,而二進位制trie樹因為每個節點最多有兩個子節點,所以也可以查詢與指定值最遠的值,即異或最大值。 (1)問題:給定一個數組,在陣列中找到兩個數,使得這兩個數的異或值最大 (2)要點:對於陣列中的每個元素,二進位制trie樹查詢異

Codeforces 811C Vladik and Memorable Trip (區間)【線性DP】

所有 一個 true sin %d 如果 不同 esp ace <題目鏈接> 題目大意: 給你n個數,現在讓你選一些區間出來,對於每個區間中的每一種數,全部都只能出現在這個區間。 每個區間的價值為該區間不同的數的異或值之和,現在問你這n個數最大的價值是多少。

RMQ——蒜頭君的玩具娃娃區間範圍-區間範圍

mes default bsp lose 格式 baseline 自己的 con using 蒜頭君有 N 個玩具娃娃,編號依次從 1 到 N,每個娃娃都有自己的高度值。蒜頭君想考考聰明的你,蒜頭君會有 Q 次詢問,每次詢問給定兩個整數 A 和 B,求問編號 A 和編號

POJ-2456 Aggressive cows---最大化也就是求

思路 cst target main include IT urn cstring strong 題目鏈接: https://vjudge.net/problem/POJ-2456 題目大意: 有n個牛欄,選m個放進牛,相當於一條線段上有 n 個點,選取 m 個點, 使得相

單調隊列 —— 滑動窗口滾動

簡單 保持 工作 影響 區間最值 因此 for 開始 += 一道經典的單調隊列題目——[洛谷P1886 滑動窗口]。(下文開始只討論求滾動的最大值) 暴力解法是O(n^2)的,對於每一個起點,搜一遍長度為k的子序列,求得最值—&mdas

算法學習——貪心算法之刪數字

size 算法學習 末尾 最小 條件 求最大值 sca 位數 技術 算法描述 在給定的n位數字,刪除其中的k位數字( k < n),使得最後的n-k為數字為最大值(原次序不變) 算法思路 考慮到是要移出數字,我們使用鏈表設計此算法較為方便,鏈表可以直接移出某個位

kuangbin專題七 HDU1754 I Hate It 單點修改維護

cond color include 專題 一次 span 修改 信息 \n 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的

NOIP2015day2 運輸計劃二分答案+差分/抽路+字首

題意 https://www.luogu.org/problemnew/show/P2680 思路 最大路徑最短,二分吧。。。然後就二分了,考試時 95

04 -pandas索引的堆行列操作,交換行列、聚合操作求和、、平均值等

引入模組 import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt 建立示例DataFrame # 用作案例 不要刪 !!! data=np.random.ra