字典树合并 ifrog1028 Bob and Alice are playing numbers

来源:互联网 发布:网络视频服务器使用 编辑:程序博客网 时间:2024/04/30 22:04

传送门:点击打开链接

题意:有3种运算符,选择两个数使用这种运算符,使得最后的答案最大。

思路:xor的我们已经很熟练了,我们来讨论&和|

&的话,如果1的个数>=2,那么我们就走1,否则,就把字典树的01合并,因为此时01的答案是一样的。

|的话,我们需要先做一个预处理。把对于每一个节点,其1所对应的字典树复制到0所对应的字典树上去。

这一步可以用DFS搞定,复杂度是T(n)=T(n/2)+n,所以总复杂度是MAX*logMAX,max等于1e6,所以可以接受

之后,我再去枚举其中一个。对于第i位,如果是1,那么我字典树就走0,如果是0,那么我字典树就走1.

因为字典树0的里面也包括了为1的值了,现在

#include <map>#include <set>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <cstdio>#include <cctype>#include <bitset>#include <string>#include <vector>#include <cstring>#include <iostream>#include <algorithm>#include <functional>#define fuck(x) cout<<"["<<x<<"]";#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("output.txt","w+",stdout);//#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long LL;typedef pair<int, int>PII;const int MX = 1e5 + 5;const int MD = 2e6 + 5;const int INF = 0x3f3f3f3f;int A[MX];int n, op, root;int nxt[MD][2], End[MD], rear;int New() {    rear++;    End[rear] = 0;    nxt[rear][0] = nxt[rear][1] = 0;    return rear;}void Init() {    rear = 0;    root = New();}void Insert(int x) {    int rt = root;    for(int i = 20; i >= 0; i--) {        int id = x >> i & 1;        if(!nxt[rt][id]) nxt[rt][id] = New();        rt = nxt[rt][id];        End[rt]++;    }}void Union(int &rt1, int rt2) {    if(!rt2) return;    if(!rt1) rt1 = New();    End[rt1] += End[rt2];    Union(nxt[rt1][0], nxt[rt2][0]);    Union(nxt[rt1][1], nxt[rt2][1]);}int query_xor(int x) {    int rt = root, ret = 0;    for(int i = 20; i >= 0; i--) {        int id = x >> i & 1;        if(nxt[rt][id ^ 1]) {            ret = ret | (1 << i);            rt = nxt[rt][id ^ 1];        } else rt = nxt[rt][id];    }    return ret;}int query_and() {    int rt = root, ret = 0;    for(int i = 20; i >= 0; i--) {        if(End[nxt[rt][1]] >= 2) {            rt = nxt[rt][1];            ret |= (1 << i);        } else {            Union(nxt[rt][0], nxt[rt][1]);            rt = nxt[rt][0];        }    }    return ret;}int solve(int x) {    int rt = root, ret = 0;    for(int i = 20; i >= 0; i--) {        int id = x >> i & 1;        if(id == 1) {            ret |= (1 << i);            rt = nxt[rt][0];        } else {            if(End[nxt[rt][1]]) {                ret |= (1 << i);                rt = nxt[rt][1];            } else rt = nxt[rt][0];        }    }    return ret;}void DFS(int rt) {    if(!rt) return;    Union(nxt[rt][0], nxt[rt][1]);    DFS(nxt[rt][0]);    DFS(nxt[rt][1]);}int query_or() {    int ret = 0; DFS(root);    for(int i = 1; i <= n; i++) {        ret = max(ret, solve(A[i]));    }    return ret;}int main() {    // FIN;    int T, ansk = 0;    scanf("%d", &T);    while(T--) {        Init();        scanf("%d%d", &n, &op);        int ans = 0;        for(int i = 1; i <= n; i++) {            scanf("%d", &A[i]);            if(op == 2) ans = max(ans, query_xor(A[i]));            Insert(A[i]);        }        printf("Case #%d: ", ++ansk);        if(op == 2) printf("%d\n", ans);        else if(op == 1) printf("%d\n", query_and());        else printf("%d\n", query_or());    }    return 0;}


0 0
原创粉丝点击