[HDU 4776 Ants] Trie异或+预处理

来源:互联网 发布:智慧树网络课程好过吗? 编辑:程序博客网 时间:2024/06/18 18:19

题目

http://acm.hdu.edu.cn/showproblem.php?pid=4776

分析

Trie异或+预处理

有点用到NOI 2011 Piano的思想的意思,因为k不大,所以把k大值一个一个都找出来

首先做一遍bfs把每个点到根的距离dist[]求出来,那么两个点的距离就是dist的异或值

然后把n个点的dist都插进trie里,然后把每个点的最大值都找出来,丢进一个堆里,然后每次取出最大的,把对应的点的下一个最大值插进堆里

找每个点的k大值可以通过在trie上记录size解决

练习赛时ans数组开小了wa了好几次

代码

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>using namespace std;typedef long long ll;const int MAX_N = 100005;const int MAX_E = 200005;const int MAX_K = 200005;const int MAX_M = 6400005;struct Node {    int size;    Node *ch[2];    Node() {        size = 0;        memset(ch, 0, sizeof(ch));    }};struct Edge {    int dest;    ll cost;    Edge *next;    Edge() {}    Edge(int _dest, ll _cost, Edge *_next) : dest(_dest), cost(_cost), next(_next) {}};Edge EdgePool[MAX_E];Edge *EP;Edge *e[MAX_N];priority_queue< pair<ll, int> > heap;Node NodePool[MAX_M];Node *NP;Node *root;int n;ll dist[MAX_N];ll ans[MAX_K];int cur[MAX_N];int Q[MAX_N];bool vis[MAX_N];inline void addedge(int a, int b, ll c) {    e[a] = new(EP++)Edge(b, c, e[a]);    e[b] = new(EP++)Edge(a, c, e[b]);}void insert(ll val) {    Node *t = root;    for (int i = 63; i >= 0; i--) {        t->size++;        int c = (int)((val >> i) & 1);        if (!t->ch[c]) {            t->ch[c] = new(NP++)Node();        }        t = t->ch[c];    }    t->size++;}ll query(ll val, int k) {    Node *t = root;    ll ret = 0;    for (int i = 63; i >= 0; i--) {        ret <<= 1;        int c = (int)((val >> i) & 1);        int _c = c ^ 1;        if (t->ch[_c] && t->ch[_c]->size >= k) {//            printf("0 (%d, %d) %d\n", _c, t->ch[_c]->size, k);            t = t->ch[_c];            ret |= _c;        }        else {//            printf("1 (%d, %d) %d\n", c, (t->ch[_c] ? t->ch[_c]->size : 0), k);            k -= t->ch[_c] ? t->ch[_c]->size : 0;            t = t->ch[c];            ret |= c;        }    }//    printf("\n");    ret ^= val;    return ret;}int main() {//    freopen("in.txt", "r", stdin);    while (scanf("%d", &n), n) {        EP = EdgePool;        memset(e, 0, sizeof(e));        NP = NodePool;        root = new(NP++)Node();        memset(dist, 0, sizeof(dist));        memset(vis, 0, sizeof(vis));        while (!heap.empty()) {            heap.pop();        }        for (int i = 1; i < n; i++) {            int a, b;            ll c;            scanf("%d %d %I64d", &a, &b, &c);            addedge(a, b, c);        }        int tail = 0;        Q[++tail] = 1;        for (int head = 1; head <= tail; head++) {            int i = Q[head];            vis[i] = true;            for (Edge *j = e[i]; j; j = j->next) {                if (!vis[j->dest]) {                    dist[j->dest] = dist[i] ^ j->cost;                    Q[++tail] = j->dest;                }            }        }        for (int i = 1; i <= n; i++) {//            printf("%I64d ", dist[i]);            insert(dist[i]);        }//        printf("\n");        for (int i = 1; i <= n; i++) {            cur[i] = 1;            ll t = query(dist[i], cur[i]);//            printf("TEST : %I64d\n", t);            heap.push(make_pair(t, i));        }        memset(ans, 0xff, sizeof(ans));        for (int i = 1; i <= 200000 && i <= (ll)n * (n - 1); i++) {            pair<ll, int> t = heap.top();            heap.pop();            ans[i] = t.first;            cur[t.second]++;            if (cur[t.second] < n) {                ll res = query(dist[t.second], cur[t.second]);//                printf("%d, %I64d, Rank %d: %I64d\n", t.second, dist[t.second], cur[t.second], res);                heap.push(make_pair(res, t.second));            }        }        int q;        scanf("%d", &q);        for (int i = 1; i <= q; i++) {            int k;            scanf("%d", &k);            printf("%I64d\n", ans[k]);        }    }    return 0;}

0 0
原创粉丝点击