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. Nginx/Apache发大招

    导读 网站程序的上传目录通常是不需要PHP执行解释权限,通过限制目录的PHP执行权限可以提网站的安全性,减少被攻击的机率. 下面和大家一起分享下如何在Apache和Nginx禁止上传目录里PHP的执行 ...

  2. Windows7 + Ubuntu双系统安装过程记录

    本文为在已安装Windows7系统的前提下安装Ubuntu Kylin 14.10系统的过程以及期间出现的各种问题的记录. Ubuntu系统下载 Ubuntu Kylin中文官方网站:http://w ...

  3. 在android程序中加入widget(窗口小部件)并与之交互的关键代码

    摘要: widget(窗口小部件)可以增强应用程序的交互性, 是很多应用中都会用到的功能,本文不求大而全,但是会给出程序与widget交互的关键代码 正文: 其实widget是嵌入(embedded) ...

  4. Webdriver配合Tesseract-OCR 自动识别简单的验证码

    验证码: 如下,在进行自动化测试,遇到验证码的问题,一般有两种方式 1.找开发去掉验证码或者使用万能验证码 2.使用OCR自动识别 使用OCR自动化识别,一般识别率不是太高,处理一般简单验证码还是没问 ...

  5. kali2.0中dradis的使用方法

    启动脚本位于:/usr/lib/dradis下,再该目录下有一个start.sh文件,执行后,可以在浏览器中输入https://localhost:3004即可打开dradis的web接口 切记前面h ...

  6. tp5 中 model 的查询方法

    实例化模型后调用查询方法,可以写任何想要的查询(推荐) public function select(){ $user = model('User'); $data = $user -> ) - ...

  7. .NET LINQ 生成操作

    生成操作      生成是指创建新的值序列. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表达式语法 更多信息 DefaultIfEmpty 将空集合替换为具有默认值的单一 ...

  8. 【Objective-C】NSDate详解及获取当前时间等常用操作

    NSDate类用于保存时间值,同时提供了一些方法来处理一些基于秒级别时差(Time Interval)运算和日期之间的早晚比较等. 1. 创建或初始化可用以下方法 用于创建NSDate实例的类方法有 ...

  9. Qt文件路径分隔符

    QDir::toNativeSeparators()QDir::separator()

  10. Win10 UWP vs add github

    vs github 插件 教程 官方教程 点击查看存储库,跳转到 DemoHttp for github