码迷,mamicode.com
首页 > 其他好文 > 详细

01trie

时间:2017-12-26 00:48:32      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:net   can   else   src   分享图片   line   pos   ble   alt   

貌似可以解决一些跟异或相关的问题?

POJ - 3764 

技术分享图片
 1 #include<vector>
 2 #include<cstdio>
 3 #include<iostream>
 4 #define pb push_back
 5 #define nc getchar
 6 #define read(x) scanf("%d", &x)
 7 using namespace std;
 8 struct Edge{int v, w, n;} E[200005];
 9 int n, d[100005], head[100005], ec;
10 inline void aE(int u, int v, int w) {
11     E[++ec] = (Edge){v, w, head[u]}; head[u] = ec;
12     E[++ec] = (Edge){u, w, head[v]}; head[v] = ec;
13 }
14 void dfs(int u, int f, int w) {
15     d[u] = w; for (int i = head[u]; i; i = E[i].n)
16         if (E[i].v != f) dfs(E[i].v, u, E[i].w ^ w);
17 }
18 struct Node {
19     Node *ch[2];
20 } Tnull, *null = &Tnull, *root;
21 Node mem[2000000], *C;
22 inline Node* newNode() {
23     C->ch[0] = C->ch[1] = null; return C++;    
24 }
25 void insert(int x) {
26     Node *u = root;
27     for (int i = 31; ~i; --i) {
28         int c = (x >> i) & 1;
29         if (u->ch[c] == null) u->ch[c] = newNode();
30         u = u->ch[c];
31     }
32 }
33 int find(int x) {
34     Node *u = root; int res = 0;
35     for (int i = 31; ~i; --i) {
36         int c = !((x >> i) & 1);
37         if (u->ch[c] == null) u = u->ch[!c];
38         else u = u->ch[c], res += 1 << i;
39     } return res;
40 }
41 void solve() {
42     for (int i = 1; i <= n; ++i) insert(d[i]);    int res = 0;
43     for (int i = 1; i <= n; ++i) res = max(res, find(d[i]));
44     printf("%d\n", res);
45 }
46 int main() {
47     while (~scanf("%d", &n)) {
48         for (int u, v, w, i = 1; i < n; ++i)
49             read(u), read(v), read(w), aE(u + 1, v + 1, w);
50         for (int i = head[1]; i; i = E[i].n) dfs(E[i].v, 1, E[i].w);
51         C = mem; root = newNode(); solve();
52         for (int i = 1; i <= n; ++i) d[i] = 0;
53         for (int i = 1; i <= n; ++i) head[i] = 0;
54         ec = 0;
55     }
56     return 0;    
57 }
View Code

这题咱用vector存边T了。

记f(i)为从根节点出发到i点时边权的异或和。

根据异或的性质,u-v这条路径的异或和就是f(u) xor f(v)。

把所有的f(i)都插入一个01trie上,然后枚举一个f(i),再贪心另一个。

BZOJ - 3261

技术分享图片
#include<cstdio>
#include<iostream>
using namespace std;
inline char nc() {
    static char b[1<<12],*s=b,*t=b;    
    return s==t&&(t=(s=b)+fread(b,1,1<<12,stdin),s==t)?-1:*s++;
}
inline void read(int &x) {
    char b = nc(); x = 0;
    for (; !isdigit(b); b = nc());
    for (; isdigit(b); b = nc()) x = x * 10 + b - 0;
}
inline int read() {
    char b = nc();
    for (; !isalpha(b); b = nc());
    return b == A;
}
struct Node {
    Node *ch[2]; int v;    
} Tnull, *null = &Tnull;
Node mem[24000010], *rt[600010], *C = mem;
inline Node* newNode() {
    C->ch[0] = C->ch[1] = null;    C->v = 0; return C++;
}
int n, m, xr;
void insert(int x, Node *u, Node *p) {
    for (int i = 24; ~i; --i) {
        int c = (x >> i) & 1;
        if (u->ch[c] == null) u->ch[c] = newNode();
        u->ch[!c] = p->ch[!c];
        u = u->ch[c]; p = p->ch[c];
        u->v = p->v + 1;
    }
}
int query(int x, Node *L, Node *R) {
    int res = 0;
    for (int i = 24; ~i; --i) {
        int c = !((x >> i) & 1);
        if (R->ch[c]->v - L->ch[c]->v > 0) res += 1 << i; else c = !c;
//        R->ch[c]->v - L->ch[c]->v > 0 ? res += 1 << i : c = !c;
        R = R->ch[c], L = L->ch[c];
    } return res;
}
int main() {
    null->ch[0] = null->ch[1] = null;
    read(n); read(m); ++n;
    rt[0] = newNode(); rt[1] = newNode(); insert(0, rt[1], rt[0]);
    for (int i = 2, t; i <= n; ++i) 
        read(t), xr ^= t, rt[i] = newNode(), insert(xr, rt[i], rt[i-1]);
    for (int x, l, r, i = 0; i < m; ++i) {
        if (read()) {
            read(x); xr ^= x; ++n; rt[n] = newNode(); insert(xr, rt[n], rt[n-1]);
        } else {
            read(l); read(r); read(x);
            printf("%d\n", query(xr ^ x, rt[l-1], rt[r]));
        }
    }    
    return 0;
}
View Code

记 f_n = a_1 xor a_2 xor ... xor a_n

即求 x xor f_n xor f_{p-1} 的最大值。

注意到 x xor f_n 为一定值,所以我们只需要在只存[l-1, r-1]这段区间值的trie上贪心就行。

01trie

标签:net   can   else   src   分享图片   line   pos   ble   alt   

原文地址:https://www.cnblogs.com/p0ny/p/8111567.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!