HDU 4776 Ants(Trie+优先队列)
Ants
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 1324 Accepted Submission(s): 289
Now in the farm come a lot of ants, which are going to enjoy the delicious apples. The ants climb the tree one by one. Every ant would choose a node as the starting node and another node as the ending node, then it would crawl alone the unique path from the starting node to the ending node. The distance between two nodes is defined as the XOR sum of lengths of all the edges in the unique path between them. Every ant wants to crawl along such a path which the distance is as large as possible. But two ants cannot crawl from the same starting node to the same ending node. You should calculate the distance which the k-th ant crawled.
Note that the starting node and the ending node cannot be the same for an ant.
For each test case, the first line contain an integer n denoting the number of nodes.
The next n-1 lines each contains three integers x,y,z, denoting that there exists an edge between node x and node y and its length is z. The nodes are numbered from 1 to n.
The next line contain a integer m denoting the number of queries.
In the next m lines, each line contains an integer k denoting that you need to calculate the distance of the k-th ant.
The input ends with n = 0.
(1 <= n, m <= 100000, 1 <= x, y <= n, 0 <= z <= 1018, 1 <= k <= 200000)
In the first test case, the first ant may crawl from node 2 to node 3, and the second ant may crawl from node 3 to node 2, and the 5-th ant may crawl from node 1 to node 3.
The distance of the 5-th ant can be calculated by 2 xor 3 = 1.
题目链接:HDU 4776
题意就是求第K大路径异或值,那很容易想到用前缀和的思想把一条路径的异或值用DFS转换成$val[u]\oplus val[v]$,其中$val[i]$是从根节点到$i$节点的路径异或和,那么题目就变成了给定大小为N个数列$val[]$,求第K大的两两异或值$val[i]\oplus val[j]$。可以先从第1大开始求,第1大很简单,对于所有的$val[i]$,找出它能异或出的最大值$val[i]\oplus val[j]$,那么这些最大值序列中全局最大的就是第1大的值,然后考虑第2大,可以发现第2大只能来自两种情况:第1大的值对应的节点下第2大的值或者是就是原来求第1大的时候第2大的值,而第3、第4大其本身和后面的迭代结果不会成为当前的第2大,因为目前的第2大已经比后面的数都大了,对于一个节点$u$,每一次去找它的第$k+1$大的值,数值必定是递减的也就是说$真实的第k大 \ge 迭代x次的第k大$,既然每一次迭代会变小,那么迭代1次总可以得到最大可能的第k大就是真实的第k大;然后就是不停地取出当前的最大值,去更新,如果这个节点更新的次数超过$n-1$次,那么就不能再更新了,因为它最多和$n-1$个数组合,即最多拥有$n-1$个异或值。
那如何用Trie求某个数的第k大的异或值呢,用主席树的思想,看当前节点的反方向子节点下的节点数是否大于等于k,如果大于等于k则可以往反方向走,否则只能正着走并用k减去节点个数
可以参照这个图理解:
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100010;
struct edge
{
int to, nxt;
LL v;
edge() {}
edge(int _to, int _nxt, LL _v): to(_to), nxt(_nxt), v(_v) {}
} E[N << 1];
struct Trie
{
int nxt[2];
int cnt;
LL v;
void init()
{
nxt[0] = nxt[1] = 0;
cnt = 0;
v = 0;
}
} L[N * 61];
struct info
{
int k;
LL val;
LL Max_xor_val;
bool operator<(const info &rhs)const
{
return Max_xor_val < rhs.Max_xor_val;
}
};
int head[N], tot;
LL arr[N];
int sz;
int n, m;
priority_queue<info>Q;
pii query[N << 1];
LL ans[N << 1]; void init()
{
CLR(head, -1);
tot = 0;
sz = 1;
L[0].init();
while (Q.size())
Q.pop();
}
inline void add(int s, int t, LL d)
{
E[tot] = edge(t, head[s], d);
head[s] = tot++;
}
void dfs(int u, int f, LL sum)
{
arr[u] = sum;
for (int i = head[u]; ~i; i = E[i].nxt)
{
int v = E[i].to;
if (v != f)
dfs(v, u, sum ^ E[i].v);
}
}
void Insert(LL val)
{
int u = 0;
for (int i = 60; i >= 0; --i)
{
int v = (val >> i) & 1;
if (!L[u].nxt[v])
{
L[sz].init();
L[u].nxt[v] = sz++;
}
u = L[u].nxt[v];
++L[u].cnt;
}
L[u].v = val;
}
LL getKth(LL val, int k)
{
if (k > n - 1)
return -1;
int u = 0;
for (int i = 60; i >= 0; --i)
{
int v = (val >> i) & 1;
int cnt = L[L[u].nxt[v ^ 1]].cnt;
if (cnt >= k)
u = L[u].nxt[v ^ 1];
else
{
k -= cnt;
u = L[u].nxt[v];
}
}
return val ^ L[u].v;
}
int main(void)
{
int u, v, i;
LL x;
while (~scanf("%d", &n) && n)
{
init();
for (i = 1; i < n; ++i)
{
scanf("%d%d%I64d", &u, &v, &x);
add(u, v, x);
add(v, u, x);
}
scanf("%d", &m);
for (i = 0; i < m; ++i)
{
scanf("%d", &query[i].first);
query[i].second = i;
}
sort(query, query + m); dfs(1, -1, 0LL);
for (i = 1; i <= n; ++i)
Insert(arr[i]);
for (i = 1; i <= n; ++i)
{
LL Max_xor_val = getKth(arr[i], 1);
if (~Max_xor_val)
Q.push({1, arr[i], Max_xor_val});
}
int Rank = 1;
for (i = 0; i < m; ++i)
{
while (!Q.empty() && Rank < query[i].first)//每次取最大的节点进行扩展
{
info now = Q.top();
Q.pop();
++now.k;
LL Max_xor_val = getKth(now.val, now.k);
if (~Max_xor_val)
{
now.Max_xor_val = Max_xor_val;
Q.push(now);
}
++Rank;
}
if (!Q.empty())
ans[query[i].second] = Q.top().Max_xor_val;
else
ans[query[i].second] = -1;
}
for (i = 0; i < m; ++i)
printf("%I64d\n", ans[i]);
}
return 0;
}
HDU 4776 Ants(Trie+优先队列)的更多相关文章
- HDU 4857 拓扑排序 优先队列
n个数,已经有大小关系,现给m个约束,规定a在b之前,剩下的数要尽可能往前移.输出序列 大小关系显然使用拓扑结构,关键在于n个数本身就有大小关系,那么考虑反向建图,优先选择值最大的入度为零的点,这样得 ...
- HDU 4857 逃生 (优先队列+反向拓扑)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 解题报告:有n个点,有m个条件限制,限制是像这样的,输入a b,表示a必须排在b的前面,如果不 ...
- HDU 1242 (BFS搜索+优先队列)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目大意:多个起点到一个终点,普通点耗时1,特殊点耗时2,求到达终点的最少耗时. 解题思路: ...
- HDU 5638 拓扑排序+优先队列
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5638 题意: 给你一个DAG图,删除k条边,使得能个得到字典序尽可能小的拓扑排序 题解: 把拓扑排序 ...
- HDU4776 Ants(Trie && xor)
之前mark下来的一道题,今天填一下坑. 题意是这样子的.给你一棵边上有权的树.然后有树上两点(u,v)的路径有n*(n-1)条,路径(u,v)的权值是边权的xor. 然后下面有m个询问,询问你n*( ...
- hdu - 1242 Rescue && hdu - 2425 Hiking Trip (优先队列+bfs)
http://acm.hdu.edu.cn/showproblem.php?pid=1242 感觉题目没有表述清楚,angel的朋友应该不一定只有一个,那么正解就是a去搜索r,再用普通的bfs就能过了 ...
- HDU 1242 Rescue(优先队列)
题目来源: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目描述: Problem Description Angel was caught by ...
- HDU 1242 Rescue(BFS+优先队列)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目描述: Problem Description Angel was caught by t ...
- HDU 2296 Ring ( Trie图 && DP && DP状态记录)
题意 : 给出 m 个单词,每一个单词有一个权重,如果一个字符串包含了这些单词,那么意味着这个字符串拥有了其权重,问你构成长度为 n 且权重最大的字符串是什么 ( 若有权重相同的,则输出最短且字典序最 ...
随机推荐
- Python3 operator模块关联代替Python2 cmp() 函数
Python2 cmp() 函数 描述 cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1. Python ...
- React学习(4)——向服务器请求数据并显示
本文中涉及到的技术包括:node.js/express服务器的搭建.fetch发送数据请求. 在之前的几篇文章中,介绍了如何搭建基础的React项目,以及一些简单知识,现在,我们还需要掌握如何用Rea ...
- mysql帐号不允许从远程登陆
默认情况下,mysql帐号不允许从远程登陆,只能在localhost登录.本文提供了二种方法设置mysql可以通过远程主机进行连接. 一.改表法 在localhost登入mysql后,更改 “mysq ...
- 图的遍历(Python实现)
图的遍历(Python实现) 记录两种图的遍历算法——广度优先(BFS)与深度优先(DFS). 图(graph)在物理存储上采用邻接表,而邻接表是用python中的字典来实现的. 两种遍历方式的代码如 ...
- Python学习:变量
变量(Variables): 是为了存储程序在运算过程中的一些中间结果,为了方便日后调用储存在计算的内存中 官方介绍: Variables are used to storeinformation t ...
- pyc是个什么鬼?
1.Python是一门解释型语音? 我初学Python时,听到的关于Python的第一句话就是,Python是一门解释型语音,我就这样一直相信下去,知道发现了*.pyc文件的存在.如果是解释型语音,那 ...
- pycharm中每次创建py文件时就自动生成代码头,以及出现SyntaxError:Non-ASCII 。。。问题
我们在pycharm中执行py文件的时候,可能会出现以下错误 这是因为你没有制定编码格式,这时候你需要在文件最开始制定编码格式,代码如下 #!/user/bin/env python #-*- cod ...
- 快速傅里叶变换(FFT)学习笔记(未完待续)
目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...
- 复位自动ID的问题有兩種方法
复位自动ID的问题 有兩種方法: 方法1: truncate table 你的表名 --這樣不但將數據刪除,而且可以重新置位identity屬性的字段. ...
- (数据科学学习手札31)基于Python的网络数据采集(初级篇)
一.简介 在实际的业务中,我们手头的数据往往难以满足需求,这时我们就需要利用互联网上的资源来获取更多的补充数据,但是很多情况下,有价值的数据往往是没有提供源文件的直接下载渠道的(即所谓的API),这时 ...