HDU 6625 세 배열이나 두 시퀀스의 최소 합 독점 배열 (복제 할 긍정적 인 솔루션

@ (HDU 6625 개의 정렬 된 시퀀스 XOR 최소 합)

질문의 의미 :

\ (T (100) \) 기, 각 길이의 두 \ (N (100,000) \) 배열은, 사용자가 수 (A는 [] \) \\ (B는 [] \) 랜덤하게 배치되어 얻을 수있다 \ (C [I]는 = A [I] \) ^ \ (B의 [I]가 \) , 작은 전적으로 발견 \을 (C [] \) .

결심

: 욕심 접근 방식은 분명히 맞다
이 질문에 대한

  • 모든이 트라이이 경우, 같은 시간에 아래로 이동합니다 \ (0 \) 또는 \ (1 \) 부담이 경로, 걷는 동안 \ (0 \을 또는 \ 1 \) 이 경로, 그 밖에는 갈 수 있습니다 \ (0 \) , 산책 \ (1 \)를 . 이러한 복잡성은 엄격 \ (O (로그) \) , 마지막으로 결과 \ (n \) 디지털 놓아 마지막 응답이다.
  • 왜 이렇게 맞아?
  • 현재 나무는 두 개의 사전이있는 경우 \ (0 \)\ (1 \) 걷는 동안 경로, \ (0 \) 확실히 번호가 서로 다른 또는 현재 최소에서 할 수 있습니다 얻을 수 있지만, 확실하게 보장되지 않으므로이 길을 그는 확실히 전적으로 작은 시퀀스에 포함 된 값이다.
  • 당신은 두 가지 간단한 01 트라이 XOR 최소 개인적인 느낌을 물어보고 싶은 경우 좋은 방법의 복잡성이 아니다.

그것은 긍정적 인 솔루션을 홍보 할 수 :

  • 주제와 사람 \ (dreamoon의 \) 긍정적 인 솔루션을 제공합니다 :
  • 지금 \ (A는 [] \) 디지털 우는에 \을 (X \) 다음 \ (B는 [] \) A 및 찾는 대응 \ (X \) 과 일치하는 숫자 XOR 최소 (Y를 \) \을 , 다음에 \ (a [] \) 찾을 내측 및 \ (Y \) 최저 수가 일치 \ (Z \) , 크기 2의 고리를 찾을 재귀 .
  • 이 반지이 두 수치는 재귀를 계속 불일치 위치의 뒤쪽으로 반출합니다.
  • 얻어진 \ (n \) 최종 답변 후 디지털 정렬.
  • 복잡성이 아이디어의 매우 과학적이고 매우 광범위한 적용됩니다.

코드 1

const int MXN = 1e5 + 7;
const int MXE = 2e6 + 7;
int n, m;
int ar[MXN], br[MXN];
struct Trie {
    int tot;
    int nex[MXE][2], num[MXE], val[MXE];
    Trie(){nex[0][0] = nex[0][1] = -1;}
    void newnode() {
        ++ tot;
        nex[tot][0] = nex[tot][1] = -1;
    }
    void inisert(int x) {
        int rt = 0;
        for(int i = 31, tmp; i >= 0; --i) {
            tmp = ((x>>i)&1);
            if(nex[rt][tmp] == -1) newnode(), nex[rt][tmp] = tot;
            rt = nex[rt][tmp];
            num[rt] ++;
        }
        val[rt] = x;
    }
    void del(int x) {
        int rt = 0;
        for(int i = 31, tmp; i >= 0; --i) {
            tmp = ((x>>i)&1);
            int lst = rt;
            rt = nex[rt][tmp];
            nex[lst][tmp] = -1;
            num[rt] = 0;
        }
    }
}cw[2];
bool check(int id, int rt, int tmp) {
    return cw[id].nex[rt][tmp] != -1 && cw[id].num[cw[id].nex[rt][tmp]] > 0;
}
int getans() {
    int rt1 = 0, rt2 = 0;
    for(int i = 31; i >= 0; --i) {
        if(check(0, rt1, 0) && check(1, rt2, 0)) {
            rt1 = cw[0].nex[rt1][0];
            rt2 = cw[1].nex[rt2][0];
            -- cw[0].num[rt1];
            -- cw[1].num[rt2];
        }else if(check(0, rt1, 1) && check(1, rt2, 1)) {
            rt1 = cw[0].nex[rt1][1];
            rt2 = cw[1].nex[rt2][1];
            -- cw[0].num[rt1];
            -- cw[1].num[rt2];
        }else if(check(0, rt1, 1) && check(1, rt2, 0)) {
            rt1 = cw[0].nex[rt1][1];
            rt2 = cw[1].nex[rt2][0];
            -- cw[0].num[rt1];
            -- cw[1].num[rt2];
        }else if(check(0, rt1, 0) && check(1, rt2, 1)) {
            rt1 = cw[0].nex[rt1][0];
            rt2 = cw[1].nex[rt2][1];
            -- cw[0].num[rt1];
            -- cw[1].num[rt2];
        }
    }
    return cw[0].val[rt1] ^ cw[1].val[rt2];
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//    freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    int tim = read();
    while(tim --) {
        n = read();
        cw[0].tot = cw[1].tot = 0;
        for(int i = 1; i <= n; ++i) ar[i] = read(), cw[0].inisert(ar[i]);
        for(int i = 1; i <= n; ++i) br[i] = read(), cw[1].inisert(br[i]);
        vector<int> vs;
        for(int i = 1; i <= n; ++i) vs.eb(getans());
        sort(all(vs));
        for(int i = 0; i < SZ(vs); ++i) printf("%d%c", vs[i], " \n"[i == SZ(vs) - 1]);
        for(int i = 1; i <= n; ++i) cw[0].del(ar[i]), cw[1].del(br[i]);
    }
    return 0;
}

CODE2

const int MXN = 1e5 + 7;
const int MXE = 2e6 + 7;
int n, m;
int ar[MXN], br[MXN];
struct Trie {
    int tot;
    int nex[MXE][2], num[MXE], val[MXE];
    Trie(){nex[0][0] = nex[0][1] = -1;}
    void newnode() {
        ++ tot;
        nex[tot][0] = nex[tot][1] = -1;
    }
    void inisert(int x) {
        int rt = 0;
        for(int i = 30, tmp; i >= 0; --i) {
            tmp = ((x>>i)&1);
            if(nex[rt][tmp] == -1) newnode(), nex[rt][tmp] = tot;
            rt = nex[rt][tmp];
            num[rt] ++;
        }
        val[rt] = x;
    }
    int query(int x) {
        int rt = 0;
        for(int i = 30, tmp; i >= 0; --i) {
            tmp = ((x>>i)&1);
            if(nex[rt][tmp] != -1 && num[nex[rt][tmp]]) rt = nex[rt][tmp];
            else rt = nex[rt][!tmp];
        }
        return val[rt];
    }
    int find() {
        int rt = 0;
        for(int i = 30, tmp; i >= 0; --i) {
            if(nex[rt][0] != -1 && num[nex[rt][0]]) rt = nex[rt][0];
            else if(nex[rt][1] != -1 && num[nex[rt][1]]) rt = nex[rt][1];
        }
        if(rt == 0) return -1;
        return val[rt];
    }
    void del() {
        for(int i = 0; i <= tot + 1; ++i) num[i] = 0, clr(nex[i], -1);
        tot = 0;
    }
    void sub(int x) {
        int rt = 0;
        for(int i = 30, tmp; i >= 0; --i) {
            tmp = ((x>>i)&1);
            rt = nex[rt][tmp];
            num[rt] --;
        }
    }
}cw[2];
/*
 * 这种做法不能保证每次求出来的异或最小值都是单调递增的,但是将n次得到的值排序后一定是正确答案
 * 如果想单纯的求两个01字典树异或最小值,个人感觉还没有较好的复杂度的做法。
 * 关于本题,还有一个出题人提供适用性更加广泛的正解:
 * 现在a中随便找一个数字,然后在b中找一个和他匹配最小的数字,再在a里面找一个和上个数匹配最小的数字,递归下去一定会找到一个大小为2的环
 * 把这个环取出来,在回到上一个位置继续递归下去。得到的n个数字排序即为最终答案。
 * */
vector<int> vs;
int dfs(int id, int x, int lst) {
    int tmp = cw[!id].query(x);
    if(tmp == lst) {
        vs.eb(tmp ^ x);
        cw[id].sub(x);
        cw[!id].sub(tmp);
        return id;
    }
    int ret = dfs(!id, tmp, x);
    if(ret != id) return ret;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//    freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    int tim = read();
    while(tim --) {
        n = read();
        for(int i = 1; i <= n; ++i) ar[i] = read(), cw[0].inisert(ar[i]);
        for(int i = 1; i <= n; ++i) br[i] = read(), cw[1].inisert(br[i]);
        vs.clear();
        while(1) {
            int tmp = cw[0].find();
            if(tmp == -1) break;
            dfs(1, tmp, -1);
        }
        sort(all(vs));
        for(int i = 0; i < SZ(vs); ++i) printf("%d%c", vs[i], " \n"[i == SZ(vs) - 1]);
        cw[0].del(), cw[1].del();
    }
    return 0;
}

원래 제목 설명

여기에 그림 삽입 설명

추천

출처www.cnblogs.com/Cwolf9/p/11330789.html