HDU4776 Ants(Trie && xor)
之前mark下来的一道题,今天填一下坑。
题意是这样子的。给你一棵边上有权的树。然后有树上两点(u,v)的路径有n*(n-1)条,路径(u,v)的权值是边权的xor. 然后下面有m个询问,询问你n*(n-1)条路径中的第k大是多少。(k<=200000)
首先树路径的xor是一个很经典的问题,首先求出所有点i到根路径的xor值val[i]。然后我们就可以发现val[u]^val[v]就是u,v路径的xor值。
然后第二个很经典的地方就是最大xor.给你一个数组,要你求数组里面xor最大的一对数。方法是根据二进制的最高位到最低位插到一棵Trie树上,然后每次询问和x xor起来最大的,就从最高位贪心地去匹配,譬如最高位是1我们就可以去匹配0。
本题的突破口在于k<=200000, 因为k小,所以我们完全可以把所有的k求出来,把询问离线一下就好了。
现在关键是我们怎么能够顺次得到第k大的呢? 方法其实很简单,首先我们对每个权值在Trie树上求出和它最大的那个,压入一个优先队列里面。然后很显然第一大的必然是优先队列的队首,然后优先队列队首的元素弹出来,这个元素里需要保存的是它是第i个结点的第k大,然后我们再把第i个结点的k+1大压入(当k达到n-1就不压了)。然后问题转化为对于一个数x,求它能匹配到的第k大,做法也很简单,Trie树上存向0走和向1走的点的个数各有多少个,如果匹配到1的时候的结点树>=k,就往匹配到1的方向走,否则就往0走,然后对应的k减去相应的值。
坑的话有两个吧,一是注意ll,二是当n=1的时候优先队列不用初始化,因为这样会把n=1当成有解的。
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
using namespace std; #define ll long long
#define maxn 150000
#define MAXCHAR 61 struct Edge
{
int v; ll w;
Edge(int _v, ll _w) :v(_v), w(_w){}
Edge(){}
}; vector<Edge> G[maxn];
ll val[maxn];
int n, m; void dfs(int u, int fa,ll vv)
{
val[u] = vv;
for (int i = 0; i < G[u].size(); i++){
int v = G[u][i].v;
ll w = G[u][i].w;
if (v == fa) continue;
dfs(v, u, vv^w);
}
} struct Trie
{
Trie *go[2];
int num[2];
void init(){
memset(go, 0, sizeof(go));
memset(num, 0, sizeof(num));
}
}*root,pool[maxn*65];
int tot; void insert(ll x)
{
Trie *p = root;
for (int i = MAXCHAR; i >= 0; i--){
int ind = (x >> i) & 1;
p->num[ind]++;
if (p->go[ind] != NULL) {
p = p->go[ind];
}
else{
pool[tot].init();
p->go[ind] = &pool[tot++];
p = p->go[ind];
}
}
} ll get(ll x, int k)
{
Trie *p = root; int kk = k; ll ret = 0;
for (int i = MAXCHAR; i >= 0; i--){
int ind = (x >> i) & 1;
if (p->num[ind ^ 1] >= kk){
ret += (1LL << i);
p = p->go[ind ^ 1];
}
else{
kk -= p->num[ind ^ 1];
p = p->go[ind];
}
}
return ret;
} struct Query
{
int k, id;
bool operator < (const Query &b) const{
return k < b.k;
}
}q[maxn]; struct Node
{
int t, k;
ll val;
Node(int _t, int _k, ll _val) :t(_t), k(_k), val(_val){}
Node(){}
bool operator < (const Node &b) const{
return val < b.val;
}
}; ll ans[maxn];
priority_queue<Node> que; int main()
{
while (cin >> n && n)
{
int ui, vi; ll wi;
for (int i = 0; i <= n; i++) G[i].clear();
for (int i = 0; i < n-1; i++){
scanf("%d%d%I64d", &ui, &vi, &wi);
G[ui].push_back(Edge(vi, wi));
G[vi].push_back(Edge(ui, wi));
}
dfs(1, -1, 0);
tot = 0; root = &pool[tot++]; root->init();
for (int i = 1; i <= n; i++){
insert(val[i]);
}
scanf("%d", &m);
for (int i = 0; i < m; i++){
scanf("%d", &q[i].k);
q[i].id = i;
}
sort(q, q + m);
while (!que.empty()) que.pop();
for (int i = 1; i <= n&&n!=1; i++){
que.push(Node(i, 1, get(val[i], 1)));
}
int cur = 0; int idx = 1;
while (!que.empty() && cur < m){
Node node = que.top(); que.pop();
if (idx== q[cur].k){
ans[q[cur].id] = node.val;
cur++; idx++;
}
else{
idx++;
}
if (node.k < n-1){
que.push(Node(node.t, node.k + 1, get(val[node.t], node.k + 1)));
}
}
for (int i = cur; i < m; i++){
ans[q[i].id] = -1;
}
for (int i = 0; i < m; i++){
printf("%I64d\n", ans[i]);
}
}
return 0;
}
HDU4776 Ants(Trie && xor)的更多相关文章
- Trie/Xor
题目链接 /*有一个数组a1,a2,a3--an.找到一个连续子段[l,r],使得al ^ al+1 ^--^ ar达到最大. 一般思路:维护前缀异或+暴力: for(int i=1;i<=n; ...
- Codeforces.842D.Vitya and Strange Lesson(Trie xor)
题目链接 /* 异或只有两种情况,可以将序列放到01Tire树上做 在不异或的情况下在Tire上查找序列的mex很容易,从高位到低位 如果0位置上数没有满,则向0递归:否则向1 (0位置上的数都满了 ...
- HDU 4776 Ants(Trie+优先队列)
Ants Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others) Total S ...
- 二分+DP+Trie HDOJ 5715 XOR 游戏
题目链接 XOR 游戏 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- [USACO]6.1.3 cow xor(二进制+Trie)
题意:给你一个序列(n<=100000),求出一个连续的子序列[i,j]使得ai xor ai+1 xor…… xor aj最大,求出这个最大值(其中每个数<=2^21) 分析:题目和求一 ...
- usaco6.1-Cow XOR:trie树
Cow XOR Adrian Vladu -- 2005 Farmer John is stuck with another problem while feeding his cows. All o ...
- 51nod1295 XOR key(可持久化trie)
1295 XOR key题目来源: HackerRank基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查询,每个查 ...
- hdu 4825 Xor Sum (01 Trie)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题面: Xor Sum Time Limit: 2000/1000 MS (Java/Others) ...
- 51nod 1295 XOR key (可持久化Trie树)
1295 XOR key 题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查 ...
随机推荐
- java-servlet-jsp
=========================servletjavax.servlet javax.servlet.http javax.annotation javax.ser ...
- Vim,一个开放源代码的文本编辑器(转)
Vim,http://linux.21ds.net/2002/03/13/0268dc26fd9c725c23dae68d797935f3/ 作者:Bram Moolenaar 翻译:slimzhao ...
- C/C++ 关于大小端模式
大端模式: 数据的高字节存在低地址 数据的低字节存在高地址 小端模式: 数据的高字节存在高地址 数据的低字节存在低地址 如图,i为int类型占4个字节,但只有1个字节的值为1,另外3个字节值为 ...
- 菜鸟学习Spring——60s让你学会动态代理原理
一.为什么要使用动态代理 当一个对象或多个对象实现了N中方法的时候,由于业务需求需要把这个对象和多个对象的N个方法加入一个共同的方法,比如把所有对象的所有方法加入事务这个时候有三种方法 ...
- centos6.5适用的国内yum源:网易、搜狐
设置方法如下: 1,进入yum源配置目录cd /etc/yum.repos.d 2,备份系统自带的yum源mv CentOS-Base.repo CentOS-Base.repo.bak 下载163网 ...
- 【EF Code First】 一对多、多对多的多重关系配置
这里使用用户表(User)和项目(Project)表做示例 有这样一个需求: 用户与项目的关系是:一个用户可以发多个项目,可以参加多个项目,而项目可以有多个参与成员和一个发布者 [其中含1-n和n-n ...
- swift 命令行工具初探
亲爱的同学们好,今天我们要介绍这么一个东西.相信有过解释型语言(PHP,Ruby,等)使用经验的同学会更加熟悉,就是 Swift 也为我们提供了命令行运行工具,俗称 REPL.好了,我们进入正题,在安 ...
- 如何配置DNS服务器(局域网——域名指向某个IP地址)
单击“开始”,指向“管理工具”,然后单击“DNS”,打开 DNS 管理器. 如有必要,向管理单元添加适用的服务器,然后连接该服务器.在控制台树中,单击适用的 DNS 服务器. 在“操作”菜单上 ...
- SQL Server数据库学习笔记-外键
关于主键的话大家很好理解,主键的主要作用就是用来标识一条数据是唯一的,也就是保证数据的实体完整性.防止数据重复.但是外键的话就有许多的疑问了,那外键是咋回事儿呢? 1. 外键的定义: 外键(FK)是用 ...
- viewport使用 html5
viewport 语法介绍: 01 02 width 控制 viewport 的大小,可以指定的一个值或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的 ...