HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 1643 Accepted Submission(s): 461
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.
题目链接: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)的更多相关文章
- HDU.4757.Tree(可持久化Trie)
题目链接 \(Description\) 给定一棵树,点有点权.\(Q\)次询问\(x,y,z\),求\(x\)到\(y\)的简单路径中,与\(z\)异或能得到的最大的数是多少. \(Solution ...
- HDU 4757 Tree 可持久化字典树 trie
http://acm.hdu.edu.cn/showproblem.php?pid=4757 给出一棵树,每个节点有权值,每次查询节点 (u,v) 以及 val,问 u 到 v 路径上的某个节点与 v ...
- HDU 4757 Tree 可持久化字典树
Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4757 Des ...
- HDU 4757 Tree(可持久化trie)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...
- HDU 4757 Tree
传送门 Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Prob ...
- 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 ...
- 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, ...
- HDU4757 Tree(可持久化Trie)
写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补. 题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少. 最原始的是数集是固定的,只需要对数集按照高到低 ...
- HDU 4757 Tree(可持续化字典树,lca)
题意:询问树上结点x到结点y路上上的权值异或z的最大值. 任意结点权值 ≤ 2^16,可以想到用字典树. 但是因为是询问某条路径上的字典树,将字典树可持续化,字典树上的结点保存在这条路径上的二进制数. ...
随机推荐
- poj 1695
用动态规划,dp[a][b][c]表示从位置最大的车在a(注意不是第一辆车),第二的车在b,第三的车在c开始最少需要的时间. 方程:dp[a][b][c]=max{dp[a+1][b][c], ...
- iOS 8.0后使用UIAlertController
iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...
- Python: zip函数
zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表. 参考链接解释
- realloc的使用误区
C语言 realloc() 函数位于 stdlib.h 头文件中,原型为: void *realloc(void *ptr, size_t size); realloc() 会将 ptr 所指向的内存 ...
- NEFU 561 方块计算
题目链接 简单搜索题 #include <cstdio> #include <iostream> #include <cstring> using namespac ...
- 使用vs2008搭建php扩展环境
所需要的工具或者文件: 1.php源码,去官网下载即可.http://windows.php.net/download 2.php-sdk:php 开发工具包 3.deps类库 4.Cygwin:wi ...
- PHP获取当前位置
如果想动态的获取当前栏目所处的位置,就要关联到数据库,下面是例子: 栏目表(category): 涉及到二级目录. (1)首先在你的首页导航栏,还有首页所出现的链接后面,为栏目加上catid,就像这样 ...
- 根据字体计算CGRect
UILabel *label = [[UILabel alloc]init]; label.numberOfLines = ;//多行显示 label.backgroundColor = [UICol ...
- C语言中的强符号与弱符号
转自:http://blog.csdn.net/astrotycoon/article/details/8008629 一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初 ...
- AutoMapper搬运工之自定义类型转换
前言 最近还挺忙,还有点累,一直都没更新了,实在是懒呀.正题之前先说点别的,最近公司要扩张了,需要大量开发,领导说推荐有钱可以拿,如此好机会,我就趁机做个广告.ShippingRen.com招募.NE ...