【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;
}
发布了242 篇原创文章 · 获赞 68 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104163900