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. JSONObject.fromObject(map)(JSON与JAVA数据的转换)

    JSON与JAVA数据的转换(JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.) 上一篇文章中有这么 ...

  2. androi手机解锁引导程序

    1.重启手机进入fastboot模式  一般关机状态下按手机音量减+开机键,成功后会显示fastboot字提示. 2.查看设备信息 fastboot devices 说明:fastboot是一个工具软 ...

  3. PDO 用法学习

    PDO: php data object数据库访问抽象层 基于驱动:1.安装扩展 php_pdo.dll2.安装驱动 php_pdo_mysql.dll linux 编译时参数:--with-pdo= ...

  4. destoon去掉会员注册email验证

    修改文件: /module/member/member.class.php 删除61行: //if(!is_email($email)) return $this->_($L['member_e ...

  5. SQL的ROW_NUMBER函数

    with tabs as ( select ROW_NUMBER() over(partition by customerID order by totalPrice) as rows,custome ...

  6. python习题 (1):login

    #!/uer/bin/env python # _*_ coding: utf-8 _*_ import sys retry_limit = 3 retry_count = 0 account_fil ...

  7. jquery input change事件

    input输入框的change事件,要在input失去焦点的时候才会触发 $('input[name=myInput]').change(function() { ... }); 在输入框内容变化的时 ...

  8. [JAVA]HTTP请求应答作输入输出

    请求(需要发送数据给别人): URL url = new URL("需要请求的URL连接"); HttpURLConnection httpConnection = (HttpUR ...

  9. 如何持续集成/交付一个开源.NET函数库到Nuget.org

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:这是一个简单的入门向导,涉及到GitHub.AppVeyor和Nuget.org. 最 ...

  10. Daily Scrum Meeting ——FourthDay

    一.Daily Scrum Meeting照片 橙汁去北京参加 ICPC比赛了,差不多15号回来 二.Burndown Chart 终于不是一条直线了..