【01字典樹插入_查找_刪除】CodeForces - 923 C. Perfect Security

 CodeForces - 923 C. Perfect Security

  • 題意:More precisely, for given A and P, find the lexicographically smallest message O, for which there exists a permutation π such that  O(i) ^ π(P(i)) == A(i)  for every i.
  • 翻譯:A數組順序不變,P數組順序可變。找到一個數組P的排列,使得對應位的Ai ^ Pi得到一個新的的序列,這個序列是所有可能可以得到的所有序列中的字典序最小的那一個。

思路

就很顯然的是01字典樹咯~因爲要找字典序最小的一個,所以我們採取貪心的策略。

對P數組建立字典樹,然後查詢與A[ i ]異或最小的數P[ k ],最重要的是不要忘記刪除P[ k ],因爲已經匹配過了嘛!【注意A[ i ]遍歷要[0, n),因爲貪心的嘛!保證遍歷過的每一個都是當前異或最小~】所以就不能再和其他匹配了。畢竟中國都是一夫一妻制(滑稽臉)~


AC CODE

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 300000 * 30 * 2 + 7;
inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n;
int a[maxN], p[maxN];
int tire[maxN][2], tot, val[maxN], cnt[maxN];
void Clear(int rt)
{
    for(int i = 0; i < 2; i ++ ) tire[rt][i] = 0;
}
void Insert(int num)
{
    int rt = 0;
    for(int i = 29; i >= 0; i -- )
    {
        int id = num >> i & 1;
        if(!tire[rt][id]) {tire[rt][id] = ++ tot; Clear(tot); }
        ++ cnt[tire[rt][id]];
        rt = tire[rt][id];
    }
    val[rt] = num;
}
void Delete(int num)
{
    int rt = 0;
    for(int i = 29; i >= 0; i -- )
    {
        int id = num >> i & 1;
        -- cnt[tire[rt][id]];
        rt = tire[rt][id];
    }
}
int Search(int num)//找到異或最小。那就找儘可能相同的咯~
{
    int rt = 0;
    for(int i = 29; i >= 0; i -- )
    {
        int id = num >> i & 1;
        if(tire[rt][id] && cnt[tire[rt][id]]) rt = tire[rt][id];
        else rt = tire[rt][id ^ 1];
    }
    return val[rt];
}
int main()
{
    Clear(0); tot = 0;
    n = read();
    for(int i = 0; i < n; i ++ )
        a[i] = read();
    for(int i = 0; i < n; i ++ )
    {
        p[i] = read();
        Insert(p[i]);
    }
    for(int i = 0; i < n; i ++ )
    {
        int ans = Search(a[i]);
        Delete(ans);
        printf("%d ", ans ^ a[i]);
    }
    printf("\n");
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章