Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 1643    Accepted Submission(s): 461

Problem Description
  Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
 
Input
  There are several test cases and the cases end with EOF. For each case:

The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

The next n–1 lines contains two integers u v, which means there is an connection between u and v.

The next m lines contains three integers x y z, which are the parameters of Zero’s query.

 
Output
  For each query, output the answer.

 
Sample Input
3 2
1 2 2
1 2
2 3
 
1 3 1
2 3 2
 
Sample Output
3
0
 

题目链接:HDU 4757

一道跟COT很像的题,但是用的是可持久化的Trie,做法跟COT基本相同,但是过程中由于N少设了10倍,无限TLE……各种纠结问题出在Tarjan?并查集?插入查询函数?因此过程中还找了题解但发现并没有什么区别,但有另外一种非递归形式的插入查询写法,值得借鉴。另外处理节点LCA的问题上公式还是那条$cnt_{U,V}=cnt_{U}+cnt_{V}-cnt_{LCA}-cnt_{father[LCA]}$

单纯地减掉两倍可能会出错,不知道网上的例程是什么情况。通过最近几道题了解了可持久化Trie的空间复杂度似乎跟Trie是一样的,都是Total*maxlen(如果撇开相对来说只有一丢丢的root数组不说的话)

递归更新查询的代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <bitset>
#include <string>
#include <deque>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=1e5+7;
struct Trie
{
int nxt[2];
int cnt;
};
struct edge
{
int to,nxt;
};
struct Query
{
int to,nxt,id,lca;
};
struct ask
{
int u,v,lca,val;
};
ask q[N];
Trie L[N*18];int cnt;
Query Q[N<<1];int qtot,qhead[N];
edge E[N<<1];int tot,head[N];
int ances[N],pre[N],Father[N];
bitset<N>vis;
int arr[N],root[N]; void init()
{
CLR(L,0);cnt=0;
CLR(head,-1);tot=0;
CLR(qhead,-1);qtot=0;
CLR(ances,0);
for (int i=0; i<N; ++i)
pre[i]=i;
CLR(Father,0);
vis.reset();
CLR(root,0);
}
inline void add(const int &s,const int &t)
{
E[tot].to=t;
E[tot].nxt=head[s];
head[s]=tot++;
}
inline void addQ(const int &s,const int &t,const int &id)
{
Q[qtot].to=t;
Q[qtot].id=id;
Q[qtot].lca=1;
Q[qtot].nxt=qhead[s];
qhead[s]=qtot++;
} void update(int &cur,const int &ori,const int &step,const int &n)
{
cur=++cnt;
L[cur]=L[ori];
++L[cur].cnt;
if(step<0)
return;
int t=(n>>step)&1;
update(L[cur].nxt[t],L[ori].nxt[t],step-1,n);
}
int Find(const int &n)
{
return n==pre[n]?n:pre[n]=Find(pre[n]);
}
void Tarjan(const int &u,const int &Fa)
{
vis[u]=1;
ances[u]=u;
Father[u]=Fa;
update(root[u],root[Fa],16,arr[u]);
for (int i=head[u]; ~i; i=E[i].nxt)
{
int v=E[i].to;
if(!vis[v])
{
Tarjan(v,u);
pre[v]=u;
ances[Find(u)]=u;
}
}
for (int i=qhead[u]; ~i; i=Q[i].nxt)
{
int v=Q[i].to;
if(vis[v])
q[Q[i].id].lca=ances[Find(v)];
}
}
int query(const int &U,const int &V,const int &LCA,const int &F_LCA,const int &step,const int &n)
{
if(step<0)
return 0;
int t=(n>>step)&1;
int c=L[L[U].nxt[t^1]].cnt+L[L[V].nxt[t^1]].cnt-L[L[LCA].nxt[t^1]].cnt-L[L[F_LCA].nxt[t^1]].cnt;
if(c>0)
return (1<<step)+query(L[U].nxt[t^1],L[V].nxt[t^1],L[LCA].nxt[t^1],L[F_LCA].nxt[t^1],step-1,n);
else
return query(L[U].nxt[t],L[V].nxt[t],L[LCA].nxt[t],L[F_LCA].nxt[t],step-1,n);
}
int main(void)
{
int n,m,a,b,i;
while (~scanf("%d%d",&n,&m))
{
init();
for (i=1; i<=n; ++i)
scanf("%d",&arr[i]);
for (i=0; i<n-1; ++i)
{
scanf("%d%d",&a,&b);
add(a, b);
add(b, a);
}
for (i=0; i<m; ++i)
{
scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].val);
addQ(q[i].u, q[i].v, i);
addQ(q[i].v, q[i].u, i);
}
Tarjan(1,0);
for (i=0; i<m; ++i)
printf("%d\n",query(root[q[i].u],root[q[i].v],root[q[i].lca],root[Father[q[i].lca]],16,q[i].val));
}
return 0;
}

网上例程的非递归写法:

int update(int ori,int n)
{
bitset<17> s=n;
int cur=++cnt;
int ret=cur;
L[cur]=L[ori];
for (int i=16; i>=0; --i)
{
int v=s[i];
L[++cnt]=L[L[cur].nxt[v]];
++L[cnt].cnt;
L[cur].nxt[v]=cnt;
cur=cnt;
}
return ret;
}
void Tarjan(const int &u,const int &Fa)
{
/*vis[u]=1;
ances[u]=u;
Father[u]=Fa;*/
root[u]=update(root[Fa],arr[u]);
/*for (int i=head[u]; ~i; i=E[i].nxt)
{
int v=E[i].to;
if(!vis[v])
{
Tarjan(v,u);
pre[v]=u;
ances[Find(u)]=u;
}
}
for (int i=qhead[u]; ~i; i=Q[i].nxt)
{
int v=Q[i].to;
if(vis[v])
q[Q[i].id].lca=ances[Find(v)];
}*/
}
int query(int u,int v,int lca,int flca,int n)
{
int r=0;
bitset<17> s=n;
for (int i=16; i>=0; --i)
{
int indx=s[i];
int c=L[L[u].nxt[indx^1]].cnt+L[L[v].nxt[indx^1]].cnt-L[L[lca].nxt[indx^1]].cnt-L[L[flca].nxt[indx^1]].cnt;
if(c>0)
{
r+=1<<i;
u=L[u].nxt[indx^1];
v=L[v].nxt[indx^1];
lca=L[lca].nxt[indx^1];
flca=L[flca].nxt[indx^1];
}
else
{
u=L[u].nxt[indx];
v=L[v].nxt[indx];
lca=L[lca].nxt[indx];
flca=L[flca].nxt[indx];
}
}
return r;
}

HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)的更多相关文章

  1. HDU.4757.Tree(可持久化Trie)

    题目链接 \(Description\) 给定一棵树,点有点权.\(Q\)次询问\(x,y,z\),求\(x\)到\(y\)的简单路径中,与\(z\)异或能得到的最大的数是多少. \(Solution ...

  2. HDU 4757 Tree 可持久化字典树 trie

    http://acm.hdu.edu.cn/showproblem.php?pid=4757 给出一棵树,每个节点有权值,每次查询节点 (u,v) 以及 val,问 u 到 v 路径上的某个节点与 v ...

  3. HDU 4757 Tree 可持久化字典树

    Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4757 Des ...

  4. HDU 4757 Tree(可持久化trie)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...

  5. HDU 4757 Tree

    传送门 Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Prob ...

  6. SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  7. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  8. HDU4757 Tree(可持久化Trie)

    写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补. 题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少. 最原始的是数集是固定的,只需要对数集按照高到低 ...

  9. HDU 4757 Tree(可持续化字典树,lca)

    题意:询问树上结点x到结点y路上上的权值异或z的最大值. 任意结点权值 ≤ 2^16,可以想到用字典树. 但是因为是询问某条路径上的字典树,将字典树可持续化,字典树上的结点保存在这条路径上的二进制数. ...

随机推荐

  1. python嵌套函数、闭包与decorator

    1 一段代码的执行结果不光取决与代码中的符号,更多地是取决于代码中符号的意义,而运行时的意义是由名字空间决定的.名字空间是在运行时由python虚拟机动态维护的,但是有时候我们希望能将名字空间静态化. ...

  2. 启动apache和tomcat端口被占用解决办法

    1,打开控制台,使用命令 netstat -aon|findstr 8090  找出端口被占用的进程, 2,使用 taskkill -f -pid 4116(进程id)杀掉当前占用端口的进程

  3. 生成解决方案,主项目的bin目录下没有其他项目生成的dll

    问题说明: 我的项目组成: 主项目为:TaskUtlity 在生成解决方案的时候在TaskUtlity的bin目录下老是找不到ProBonus项目生成的dll. 解决方案: 1.打开sln文件,找到P ...

  4. PHP程序员进阶学习书籍参考指南

    PHP程序员进阶学习书籍参考指南 @heiyeluren lastmodify: 2016/2/18     [初阶](基础知识及入门)   01. <PHP与MySQL程序设计(第4版)> ...

  5. 一个国家专利查询demo

    写了一下午,借鉴apache的 httpclient 源码 调用 写的,拿出来分享一下,可以用作其他不同平台的项目post/get数据上面. package cn.shb.test; import o ...

  6. word如何插入目录

    word如何插入目录 百度经验:jingyan.baidu.com 在写文章的时候我们需要插入目录,如果自己手动添加目录会非常麻烦,以后修改文章的时候还得修改目录的页码,还好Word中有自动添加目录的 ...

  7. Java Class类及反射机制

    java.lang.Class类 声明: public final class Class<T>extends Object implements Serializable, Generi ...

  8. PHP 基础(赋值及函数)

    开端<?php>结尾</php> 弱类型语言  定义变量的时候 不需要 声明   但是 每一个变量前   都必须  加$ 符号 储存文件按  统一放到 安装文件夹下面的  WA ...

  9. 学习android推荐网站

    1. Android Developers 作为一个Android开发者,官网的资料当然不可错过,从设计,培训,指南,文档,都不应该错过,在以后的学习过程中慢慢理解体会. 2. Android Gui ...

  10. MySql中的字符数据类型

    MySql中的varchar类型 1.varchar类型的变化 MySQL数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255根据不同版本数据库 ...