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. sscanf提取字符串中的数据php

    1.需求 理解sscanf的作用 2.例子 $str = "age:30 weight:60kg"; sscanf($str,"age:%d weight:%dkg&qu ...

  2. React 还是 Vue: 你应该选择哪一个Web前端框架?

    学还是要学的,用的多了,也就有更多的认识了,开发中遇到选择的时候也就简单起来了. 本文作者也做了总结: 如果你喜欢用(或希望能够用)模板搭建应用,请使用Vue    如果你喜欢简单和“能用就行”的东西 ...

  3. C#高级编程笔记 Day 4, 2016年9月 12日(接口)

    1.定义和实现接口:接口名称通常上以字母 I 开头 例子:定义IBankAccount接口 namespace Test.YinXi{ public interface IBankAccount{ v ...

  4. JavaScript 加载动画Canvas 设计

    var c = document.getElementById('c'), ctx = c.getContext('2d'), cw = c.width = 400, ch = c.height = ...

  5. C Primer Plus_第5章_运算符、表达式和语句_编程练习

    Practice 1. 输入分钟输出对应的小时和分钟. #include #define MIN_PER_H 60 int main(void) { int mins, hours, minutes; ...

  6. linux svn 搭建

    原文:http://jingyan.baidu.com/article/3c343ff7039de20d37796306.html和http://blog.sina.com.cn/s/blog_670 ...

  7. LeetCode之389. Find the Difference

    -------------------------------------------------- 先计算每个字母的出现次数然后减去,最后剩下的那一个就是后来添加的了. AC代码: public c ...

  8. Sublime Text3 安装markdown插件

    1.打开Sublime Text,使用快捷键 ctrl+` (左上角Tab键上方,Esc键下方)或者使用菜单 View > Show Console menu,此时将出现Sublime Text ...

  9. [C++11][数据结构]自己的双链表实现

    这个双链表,是我模仿stl的list制作的,只实现了一些基本功能,像merge,transfer这些就没有实现,用户可以用基本操作来自己做外部实现. 我没有选用stl的[begin,end)迭代器模式 ...

  10. git学习(二):查看状态和具体改动

    查看仓库状态 git status 可以查看有没有文件改动 查看改动情况 git diff readme.txt 以readme.txt为例,可以看readme.txt的改动情况,但对于二进制文件来说 ...