HDU 4776 Ants tire+优先队列

来源:互联网 发布:mac内存清理软件 编辑:程序博客网 时间:2024/05/16 11:12

【题目大意】

有一棵树,树上一条简单路径(u,v)的价值定义为这条路径的所有边的异或和。求这些价值的第k大。

【思路】

如果我们统计根到节点u,路径的异或和为a[u],显然,路径(u,v)的价值为a[u]^a[v]。问题变为了从n个数中选两个不同的数,求异或,找第k大。因为k其实不是很大,我们可以考虑将1-max(k)的价值都找出来。用a[]建立tire树,首先枚举路径的左端点,通过tire找到一个右端点,使得其异或值最大。把这些数加入优先队列,显然,这些数中,最大的那个,就是第一大的价值。然后把这个价值删掉,通过原来的左端点,再找一个右端点,使其异或值变成次大,并把这个值加入优先队列。这个时候,队列中最大的元素是第二大的价值。这样一直找下去,就能把所有k都找到。

#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef __int64 LL;//typedef unsigned __int64 ULL;/* ****************** */const LL INF = 1LL<<55;const double INFF = 1e100;const double eps = 1e-8;const LL mod = 10000000007LL;const int NN = 100010;const int MM = 5000010;/* ****************** */const int limit = 59;struct G{    int v, next;    LL w;}E[NN*2];int p[NN], T;struct node{    LL x, x_xor;    int num;    node(LL a = 0,LL b = 0,int c = 0):x(a),x_xor(b),num(c){}    bool operator<(const node &tt)const    {        return x_xor < tt.x_xor;    }};LL a[NN];struct Tire{    int num;    int ch[2];    void init()    {        num = 0;        memset(ch, -1, sizeof(ch));    }}tire[NN*60];struct Q{    int k, id;    bool operator<(const Q &tt)const    {        return k < tt.k;    }}q[NN];LL anss[NN];void add(int u,int v,LL w){    E[T].v = v;    E[T].w = w;    E[T].next = p[u];    p[u] = T++;}void dfs(int u,int fa){    int i, v;    for(i = p[u]; i + 1; i = E[i].next)    {        v = E[i].v;        if(v == fa)continue;        a[v] = a[u]^E[i].w;        dfs(v, u);    }}void tire_insert(LL val,int root,int &tire_cnt){    int i, x, p = root;    for(i = limit; i >=0; i --)    {        if(val&(1LL<<i))            x = 1;        else            x = 0;        if(tire[p].ch[x]==-1)        {            tire[p].ch[x] = ++tire_cnt;            tire[tire_cnt].init();        }        p = tire[p].ch[x];    }    tire[p].num ++;}LL tire_find_max(LL val,int root,int &num){    int i, x, p = root;    LL ans = 0;    for(i = limit; i >= 0; i --)    {        if(val&(1LL<<i))            x = 0;        else            x = 1;        if(tire[p].ch[x]!=-1)        {            ans |= (1LL<<i);            p = tire[p].ch[x];        }        else        {            p = tire[p].ch[x^1];        }    }    num = tire[p].num;    return ans;}LL tire_find_lower(LL val,LL x_xor,int root,int &num){    int i, x, xx, p = root;    int last = -1;    LL ans = 0;    for(i = limit; i >= 0; i --)    {        if( (val^x_xor)&(1LL<<i) )            x = 1;        else            x = 0;        if( val&(1LL<<i))            xx = 0;        else            xx = 1;        if(tire[p].ch[x^1]!=-1 && x == xx)            last = i;        p = tire[p].ch[x];    }    if(last==-1)return -1;    p = root;    for(i = limit; i >= 0; i--)    {        if(i >= last)        {            if( (val^x_xor)&(1LL<<i) )                x = 1;            else                x = 0;            if(i == last)                x = (x^1);        }        else        {            if(val&(1LL<<i))                x = 0;            else                x = 1;            if(tire[p].ch[x]==-1)                x = (x^1);        }        if( ( val^((LL)x<<i) )&(1LL<<i) )            ans |= (1LL<<i);        p = tire[p].ch[x];    }    num = tire[p].num;    return ans;}void solve(int n,int m){    int i, j, tire_root, tire_cnt, num;    LL t;    priority_queue<node>my_q;    tire_root = tire_cnt = 0;    tire[tire_root].init();    for(i = 1; i <= n; i ++)    {        tire_insert(a[i], tire_root, tire_cnt);    }    for(i = 1; i <= n; i ++)    {        t = tire_find_max(a[i], tire_root, num);        my_q.push( node(a[i], t, num) );    }    j = 1;    memset(anss, -1, sizeof(anss));    for(i = 1; i <= (LL)n*(n-1) && j <= m ; i ++)    {        node ix = my_q.top();        my_q.pop();        while(j <= m && i==q[j].k)        {            anss[q[j].id] = ix.x_xor;            j ++;        }        if(ix.num > 1)        {            my_q.push( node(ix.x, ix.x_xor, ix.num-1) );        }        else        {            t = tire_find_lower(ix.x, ix.x_xor, tire_root, num);            if(t!=-1)                my_q.push( node(ix.x, t, num) );        }    }    for(i = 1; i <= m; i ++)        printf("%I64d\n", anss[i]);}int main(){    int n, m, u, v, i;    LL t;    while(scanf("%d", &n) != EOF)    {        if(n==0)break;        memset(p, -1, sizeof(p));        T = 0;        for(i = 1; i < n; i ++)        {            scanf("%d%d", &u, &v);            scanf("%I64d", &t);            add(u, v, t);            add(v, u, t);        }        a[1] = 0;        dfs(1,-1);        scanf("%d", &m);        for(i = 1; i <= m; i ++)        {            scanf("%d", &q[i].k);            q[i].id = i;        }        sort(q+1,q+1+m);        solve(n, m);    }    return 0;}


0 0
原创粉丝点击