1. 程式人生 > >HDU 4776 (字典樹)

HDU 4776 (字典樹)

題意:

        一棵樹,有邊權,路徑價值為所有邊權異或的值,m次查詢,每次查詢第k大的路徑的價值

標題思路:

        從1dfs出其他點到1的路徑的值,我們發現任意一條路徑可以表示為兩個值相異或,這樣題目就變成了n個數,問任意兩個異或的值中的第k大。
        先將這n個數放到字典樹中,我們再將這n個數分別跑一次字典樹,這樣能跑出當前最大的值,把這些值放到優先佇列中,此刻最大的值就是異或出的最大的值,然後我們把這個點拿出來,再跑一次字典樹,去尋找第二大的值,這樣優先佇列中最大的值就是第二大的,這樣不斷重複就能得到前k大了,複雜度O(nlogn2)O(nlogn^2 )

nlogn2)

錯誤及反思:

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#define mst(x,a) memset(x,a,sizeof(x))
#define all(x) (x).begin(),(x).end()
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int> pii;
typedef long long ll;
typedef vector<int> vi;
#define fi first
#define se second
#define sz(x) ((int)x.size())
#define cl(x) x.clear()
const int mod = 1000000007;
const int N = 100010;
void MOD(ll &a){if(a>=mod) a-=mod;}
void MOD(ll &a,ll c){if(a>=c) a-=c;}
void ADD(ll &a,ll b){ a+=b; MOD(a);}
void ADD(ll &a,ll b,ll c){a+=b;MOD(a,c);}
ll qpow(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b/=2;}return ans;}
ll qpow(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c;b/=2;}return ans;}

int tot,head[N],n;
struct EDGE{
    int to,nex;
    ll val;
}e[N*2];

ll a[N];

void addedge(int u,int v,ll x){
    e[tot].to=v;
    e[tot].val=x;
    e[tot].nex=head[u];
    head[u]=tot++;
}

int nex[N*62][2],cnt[N*62];
int root,sz;

int newnode(){
    nex[sz][0]=nex[sz][1]=cnt[sz]=0;
    return sz++;
}

void Insert(ll x){
    int now=root;
    cnt[now]++;
    for(int i=61;i>=0;i--){
        if(x&(1ll<<i)){
            if(!nex[now][1]) nex[now][1]=newnode();
            now=nex[now][1];
        }
        else{
            if(!nex[now][0]) nex[now][0]=newnode();
            now=nex[now][0];
        }
        cnt[now]++;
    }
}

ll query(ll x,int k){
    int now=root;
    ll res=0;
    for(int i=61;i>=0;i--){
        if(x&(1ll<<i)){
            if(nex[now][0]&&cnt[nex[now][0]]>=k){
                res+=(1ll<<i);
                now=nex[now][0];
            }
            else{
                if(nex[now][0]) k-=cnt[nex[now][0]];
                now=nex[now][1];
            }
        }
        else{
            if(nex[now][1]&&cnt[nex[now][1]]>=k){
                res+=(1ll<<i);
                now=nex[now][1];
            }
            else{
                if(nex[now][1]) k-=cnt[nex[now][1]];
                now=nex[now][0];
            }
        }
    }
    return res;
}

void dfs(int now,int fa,ll tmp){
    a[now]=tmp;
    for(int i=head[now];i!=-1;i=e[i].nex){
        if(e[i].to==fa) continue;
        dfs(e[i].to,now,tmp^e[i].val);
    }
}

struct si{
    ll val,ori,k;
    bool operator < (const si& shr) const{
        return val<shr.val;
    }
};

priority_queue<si> pq;
ll fin[N*2];

void init(){
    while(!pq.empty()) pq.pop();
    sz=0;
    root=newnode();
    tot=0;
    mst(head,-1);
}
int qus[N];
int main(){
    while(scanf("%d",&n)&&n){
        init();
        for(int i=1;i<n;i++){
            int u,v; ll x;
            scanf("%d%d%lld",&u,&v,&x);
            addedge(u,v,x); addedge(v,u,x);
        }
        dfs(1,1,0);
        for(int i=1;i<=n;i++) Insert(a[i]);

        for(int i=1;i<=n;i++){
            ll x=query(a[i],1);
            pq.push({x,a[i],1});
        }
        int m; scanf("%d",&m);
        int mx=1;
        for(int i=0;i<m;i++){
            scanf("%d",&qus[i]);
            mx=max(mx,qus[i]);
        }
        for(int i=1;i<=mx;i++){
            if(pq.empty()) break;
            si x=pq.top();
            fin[i]=x.val;
            pq.pop();
            x.k++;
            if(x.k<n){
                x.val=query(x.ori,x.k);
                pq.push(x);
            }
        }
        for(int i=0;i<m;i++){
            if(qus[i]>1ll*n*(n-1))
                printf("-1\n");
            else printf("%lld\n",fin[qus[i]]);
        }
    }
}

相關推薦

HDU 4776 字典

題意:         一棵樹,有邊權,路徑價值為所有邊權異或的值,m次查詢,每次查詢第k大的路徑的價值 標題思路:         從1dfs出其他點到1的路徑的值,我們發現任意一條路徑可以表示為兩個值相異或,這樣題目就變成了n個數,問任意兩個異或的值中的第k

統計難題HDU-1251字典

wkt mtu shp isl com shuf rrd xe8 xdg yhly5c梅覆來粕倜叛http://docstore.docin.com/sina_6341912133p1s7b1澇淪家濤缺細http://www.docin.com/gxk352s1mtus俟酚

[ACM] hdu 1251 統計難題 字典

第一次 stdio.h scrip null 明顯 output 代碼 ane 處理 統計難題 Problem Description Ignatius近期遇到一個難題,老師交給他非常多單詞(僅僅有小寫字母組成,不會有反復的單詞出現),如今老師要他統計出以某

HDU 6059 17多校3 Kanade's trio字典

要求 tro none sat details num cst void stream Problem Description Give you an array A[1..n],you need to calculate how many tuples (i,j,k)

HDU 1247 Hat’s Words字典

ota log ted family lar line 初始 ber problems Hat’s Words Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other

HDU 1251 - 統計難題 字典

Ignatius最近遇到一個難題,老師交給他很多單詞(只有小寫字母組成,不會有重複的單詞出現),現在老師要他統計出以某個字串為字首的單詞數量(單詞本身也是自己的字首). Input 輸入資料的第一部分是一張單詞表,每行一個單詞,單詞的長度不超過10,它們代表的是老師交給Ignatius統計的

HDU 4825 字典 +貪心

Zeus 和 Prometheus 做了一個遊戲,Prometheus 給 Zeus 一個集合,集合中包含了N個正整數,隨後 Prometheus 將向 Zeus 發起M次詢問,每次詢問中包含一個正整數 S ,之後 Zeus 需要在集合當中找出一個正整數 K ,使得 K 與 S 的異或結果最大。Pr

HDU 1671 字典 || string + vector

目錄 題意: 思路: 1.字典樹 題意: T個案例,每一個案例給一個n,代表有n個號碼,接著輸入n個號碼。 如果其中有一個號碼是另一個號碼的字首則輸出NO,否則輸出YES。 思路: 1.字典樹 第一反應是字典樹、字首樹嘛……但是之前覺得就很難,不敢寫

HDU 1075.What Are You Talking About【Map水題字典】【5月25】

What Are You Talking About Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/204800 K (Java/Others) Total Submission(s): 1

HDU 6059 Kanade's trio字典

Description 給出一個長度為n的序列A[1]~A[n],求滿足i < j < k且(A[i]^A[j])<(A[j]^A[k])的三元組(i,j,k)個數 Input 第一行一整數T表示用例組數,每組用例首先輸入一整數n表示序列

HDU 1671 Phone List字典

Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Le

hdu Phone List 字典

Phone List Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 4   Accepted Submiss

HDU 1251 統計難題字典

#include<stdio.h> #include<string.h> struct Node { Node *next[26];//每個節點的分支由單詞性質決定,這裡是小寫的26個字母 int cnt;//每個節點可以儲存一些資訊,這道題是儲存該字首的數量 Node()

*hdu 5536字典的運用

Input The first line of input contains an integer T indicating the total number of test cases. The first line of each test case is an

Trie字典1

stdio.h public ctu 哈希 pac 索引 cas proc ren   Trie樹。又稱字典樹,單詞查找樹或者前綴樹,是一種用於高速檢索的多叉樹結構。   Trie樹與二叉搜索樹不同,鍵不是直接保存在節點中,而是由節點在樹中的位置決定。

[BZOJ1590] [Usaco2008 Dec]Secret Message 秘密信息字典

clu har pro iostream digi git secret 秘密 class 傳送門 看到前綴就要想到字典樹! 看到前綴就要想到字典樹! 看到前綴就要想到字典樹! #include <cstdio> #include &l

trie字典

arc delete png 技術分享 我只 blog 存在 紅色 style 核心思想: 利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的 舉個例子 上圖是由 am as tea too tooth two 構成的字典樹。每個節

Trie tree字典

pri table main radix gcc編譯器 out 字典 name dia   Trie tree有時被稱為(digital tree)或(radix tree or prefix tree)。   可能是編譯器問題,我的實現方法用gcc編譯器,debug沒問

hdu 3473 劃分2

mage def typedef sin else BE IT ext cati Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

hdu1075字典

pid 換行 現在 img trie 單詞 word pen 字典 What Are You Talking About 題意:   給出Martian的語言的單詞對應的英語單詞以及一段用Martian的語言寫成的文本,現在要求把文本翻譯成英文,文本中的空格,換行,‘\t’