bzoj 2588: Spoj 10628. Count on a tree(树上主席树)
来源:互联网 发布:无法登录战网检查网络 编辑:程序博客网 时间:2024/06/05 10:50
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3980 Solved: 932
[Submit][Status][Discuss]
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
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
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。
Source
鸣谢seter
大体思路就是对树上的每个点权进行离散化,然后对树上的的每一个节点到根的路径建一棵权值线段树,因为这些树形态结构都是相似的所有可以进行加减运算(主席树特性)。那么x,y两点之间的路径就可以表示成root[x]+root[y]-root[lca(x,y)]-root[fa[lca(x,y)],然后进行求解即可。
遇到的问题:直接对每一个节点建立的权值线段树,没有按照DFS序建树,于是RE了。为什么呢?因为在建树时是动态开点,也就是在他父亲所在的树上新开了一些节点,如果直接建树,有可能父亲节点还没有建,当前点就建立了。果然我还是太水了。。。。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 100003#define M 6000000using namespace std;int a1[N],p[N],b1[N],n,m;int v[N*2],point[N],next[N*2],tot;int fa[N][20],mi[20],deep[N],sz,cnt,num[N],pos[N];int ls[M],rs[M],sum[M],root[N],nm,pd[N];int cmp(int x,int y){return a1[x]<a1[y];}void add(int x,int y){ tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;}void dfs(int x,int f){pos[x]=++sz; num[sz]=x; for (int i=1;i<=17;i++) { if (deep[x]-mi[i]<0) break; fa[x][i]=fa[fa[x][i-1]][i-1]; }for (int i=point[x];i;i=next[i]) if (v[i]!=f) { fa[v[i]][0]=x; deep[v[i]]=deep[x]+1; dfs(v[i],x); }}void build(int l,int r,int fa,int &k,int v){k=++nm; ls[k]=ls[fa]; rs[k]=rs[fa];int mid=(l+r)/2;sum[k]=sum[fa]+1;if (l==r) return ;if (v<=mid) build(l,mid,ls[fa],ls[k],v);else build(mid+1,r,rs[fa],rs[k],v);}int lca(int x,int y){if (deep[x]<deep[y]) swap(x,y);int k=deep[x]-deep[y];for (int i=0;i<=17;i++) if ((k>>i)&1) x=fa[x][i];if (x==y) return x;for (int i=17;i>=0;i--) if (fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } return fa[x][0];}int query(int x,int y,int k){int c=lca(x,y); int d=fa[c][0];int l=1; int r=cnt;int a=root[pos[x]]; int b=root[pos[y]]; c=root[pos[c]]; d=root[pos[d]];while (l<r) { int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; int mid=(l+r)/2; if (k<=tmp) { a=ls[a]; b=ls[b]; c=ls[c]; d=ls[d]; r=mid; } else { a=rs[a]; b=rs[b]; c=rs[c]; d=rs[d];l=mid+1; k-=tmp; } }return a1[pd[l]];} int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%d",&a1[i]),p[i]=i;sort(p+1,p+n+1,cmp); cnt=0;for (int i=1;i<=n;i++) if (a1[p[i]]!=a1[p[i-1]]) cnt++,b1[p[i]]=cnt,pd[cnt]=p[i]; else b1[p[i]]=cnt;for (int i=1;i<n;i++) { int x,y;scanf("%d%d",&x,&y); add(x,y); }deep[1]=1; mi[0]=1;for (int i=1;i<=17;i++) mi[i]=mi[i-1]*2;dfs(1,0);for (int i=1;i<=n;i++){ int t=num[i]; build(1,cnt,root[pos[fa[t][0]]],root[i],b1[t]); }int last=0;for (int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); x^=last; last=query(x,y,z);if (i!=m) printf("%d\n",last);else printf("%d",last); }}
0 0
- bzoj 2588: Spoj 10628. Count on a tree(树上主席树)
- BZOJ BZOJ 2588: Spoj 10628. Count on a tree 树上主席树
- 【BZOJ 2588】 Spoj 10628. Count on a tree|树上K大|树链剖分|主席树
- 【BZOJ 2588】Spoj 10628. Count on a tree 主席树+树上差分
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- [主席树] BZOJ 2588 Spoj 10628. Count on a tree
- BZOJ 2588 Spoj 10628. Count on a tree 主席树
- Spoj 10628. Count on a tree 树上主席树
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)
- BZOJ 2588 Count on a tree(树上的主席树)
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
- [BZOJ]2588: Spoj 10628. Count on a tree 主席树+LCA
- 【BZOJ】2588 Spoj 10628. Count on a tree LCA+主席树
- 2588: Spoj 10628. Count on a tree 主席树+LCA
- SPOJ Count on a tree(lca+主席树,树上主席树,好题)
- 【BZOJ 2588】Count on a tree 【树上路径第K大】【LCA+主席树】
- 【主席树】 SPOJ Count on a tree
- 远程连接mysql/mariaDB数据库时出现1045错误
- 204. Count Primes
- 关于居中
- CM和CMTS的概念和信令交互过程
- tableView中的cell复制粘贴操作
- bzoj 2588: Spoj 10628. Count on a tree(树上主席树)
- IOS总体学习思路(16.5.1)
- 是时候贴上校园漫游的成品了【记录】
- 如何复制cmd命令行文字
- ActiveMQ小记(一):监控
- AndroidStudio中使用Git-初级篇(一)——从github上传和下载项目(by 星空武哥)
- Hadoop2.*源码分析之Job任务提交与执行
- Linux基本命令01
- 运行时机制修改UIAlertController文字对齐方式