bzoj2588:Count on a tree(可持久化线段树+Lca)
来源:互联网 发布:照片说话软件 编辑:程序博客网 时间:2024/05/01 05:39
2588: Spoj 10628. Count on a tree
Time Limit: 12Sec Memory Limit: 128 MB
Submit: 5524 Solved: 1306
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
Input
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
Output
M行,表示每个询问的答案。最后一个询问不输出换行符
Sample Input
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
Sample Output
2
8
9
105
7
HINT
HINT:
N,M<=100000
题目分析:可持久化线段树,一个节点以它的fa的线段树作为历史版本做适当修改。当我们要查u->v的路径第k小时,我们同时在u,v,lca(u,v),fa[lca(u,v)]四棵树上进行二叉查找。
写代码的时候发现与其将空子树指向NULL还不如指向池子的第0位,然后让第0位指向自身。这样Query的时候就可以在0的地方不停地打转,不会爆栈。
没看清输出格式,PE了一发……
CODE:
#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>using namespace std;const int maxn=100100;const int maxl=20;const int oo=1000000001;struct data{int obj;data *Next;} e[maxn<<1];data *head[maxn];int cur=-1;struct Tnode{int num;Tnode *lson,*rson;} tree[(maxn<<2)+maxn*maxl];Tnode *Root[maxn];int Tcur=-1;struct Input{int Time,val,place;} a[maxn];int id[maxn];int temp=0;int fa[maxn][maxl];int dep[maxn];int n,m;void Add(int x,int y){cur++;e[cur].obj=y;e[cur].Next=head[x];head[x]=e+cur;}bool Comp1(Input x,Input y){return x.val<y.val;}bool Comp2(Input x,Input y){return x.Time<y.Time;}Tnode *New_node(){Tcur++;tree[Tcur].lson=tree[Tcur].rson=tree;tree[Tcur].num=0;return tree+Tcur;}void Update(Tnode *root,int L,int R,int x){if ( L==x && x==R ){root->num++;return;}int mid=(L+R)>>1;if (x<=mid){Tnode *y=root->lson;root->lson=New_node();*(root->lson)=*y;Update(root->lson,L,mid,x);}else{Tnode *y=root->rson;root->rson=New_node();*(root->rson)=*y;Update(root->rson,mid+1,R,x);}root->num=root->lson->num+root->rson->num;}void Dfs(int node){Root[node]=New_node();*Root[node]=*Root[ fa[node][0] ];Update(Root[node],1,temp,a[node].place);data *p;for (p=head[node]; p; p=p->Next)if (p->obj!=fa[node][0]){int son=p->obj;fa[son][0]=node;dep[son]=dep[node]+1;Dfs(son);}}void Make_fa(){for (int j=1; j<maxl; j++)for (int i=1; i<=n; i++)fa[i][j]=fa[ fa[i][j-1] ][j-1];}int Lca(int u,int v){if (dep[u]<dep[v]) swap(u,v);for (int j=maxl-1; j>=0; j--)if ( dep[ fa[u][j] ]>=dep[v] )u=fa[u][j];if (u==v) return u;for (int j=maxl-1; j>=0; j--)if (fa[u][j]!=fa[v][j]){u=fa[u][j];v=fa[v][j];}return fa[u][0];}int Query(Tnode *ru,Tnode *rv,Tnode *rw,Tnode *rfw,int L,int R,int k){if (L==R) return L;int left_num=ru->lson->num+rv->lson->num-rw->lson->num-rfw->lson->num;int mid=(L+R)>>1;if (k<=left_num) return Query(ru->lson,rv->lson,rw->lson,rfw->lson,L,mid,k);else return Query(ru->rson,rv->rson,rw->rson,rfw->rson,mid+1,R,k-left_num);}int main(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1; i<=n; i++) scanf("%d",&a[i].val);for (int i=1; i<=n; i++) a[i].Time=i;for (int i=1; i<=n; i++) head[i]=NULL;for (int i=1; i<n; i++){int x,y;scanf("%d%d",&x,&y);Add(x,y);Add(y,x);}a[0].val=-oo;sort(a+1,a+n+1,Comp1);for (int i=1; i<=n; i++){if (a[i-1].val!=a[i].val) temp++;a[i].place=temp;id[temp]=a[i].val;}sort(a+1,a+n+1,Comp2);//for (int i=1; i<=temp; i++) printf("%d ",id[i]);//printf("\n");Root[0]=New_node();fa[1][0]=0;dep[1]=1;Dfs(1);Make_fa();/*for (int j=0; j<maxl; j++){for (int i=1; i<=n; i++) printf("%d ",fa[i][j]);printf("\n");}*/int lastans=0;for (int i=1; i<=m; i++){int u,v,k;scanf("%d%d%d",&u,&v,&k);u=u^lastans;int w=Lca(u,v);//printf("%d\n",w);lastans=Query(Root[u],Root[v],Root[w],Root[ fa[w][0] ],1,temp,k);lastans=id[lastans];printf("%d",lastans);if (i!=m) printf("\n");}return 0;}
0 0
- bzoj2588:Count on a tree(可持久化线段树+Lca)
- 【BZOJ2588】【Spoj 10628.】 Count on a tree 可持久化线段树+lca
- [BZOJ2588]Spoj 10628. Count on a tree 可持久化线段树
- [BZOJ2588]Count on a tree(可持久化权值线段树|主席树)
- 2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]
- BZOJ 2588 Count on a tree 可持久化线段树+LCA
- 【bzoj2588】Spoj 10628. Count on a tree LCA+主席树
- 【BZOJ2588】Spoj 10628. Count on a tree【主席树】【LCA】
- 洛谷 P2633 Count on a tree[bzoj2588](倍增lca+主席树)
- bzoj2588 count on a tree 主席树
- 【bzoj2588】Count on a tree 主席树
- [bzoj2588][主席树]Count on a tree
- BZOJ 2588 Count on a tree (COT) 可持久化线段树
- 【可持久化线段树】[SPOJ COT]Count on a tree
- 【spoj】【COT - Count on a tree】【可持久化线段树】
- [BZOJ2588][Spoj10628]Count on a tree(树上主席树)
- 【BZOJ2588】Count On a Tree(主席树)
- bzoj2588 Count on a tree
- POJ 2240Arbitrage
- 在LCD上实现简易电子钟
- 用c++对一个5位数的任意整数,求出其降序数。例如,整数是82319,则其降序数是98321。试建立一个类DescendNUM,用于完成该功能。
- 关于成为一名嵌入式程序员的日常总结(7)
- 【PAT】1092. To Buy or Not to Buy
- bzoj2588:Count on a tree(可持久化线段树+Lca)
- xv6源码分析(七):文件系统
- 微信开发二之关键字回复
- JavaScript动态向表格添加数据
- 如何使用CSS
- 素数;最大公约数和最小公倍数;“冒泡”问题
- HDU 3085 Nightmare 双向bfs
- ubuntu16.04下安装cuda8.0
- ToolStripMenuItem