BZOJ 2588 & SPOJ 10628:树上主席树
来源:互联网 发布:iptv服务器软件 编辑:程序博客网 时间:2024/05/16 17:13
BZOJ强制在线,所以大多数RE==WA
SPOJ比较坑,大多数WA是因为数组没开够(n实际上大于1e5。。。题目数据的锅)。
题意:给出一棵树,树上每个点有一个权值,现在有若干询问,每次询问(u,v,k)求出u-v路径上权值第k小的是什么。
题解:在树上构造主席树,每个点记录该点到根路径上所有点。然后u-v的路径 需要用 u+v-lca(u,v)-father[lca(u,v)]来得到,画个图或者想象一下是很好理解的。
注意LCA不要写丑了。
代码:
#include<bits/stdc++.h>#define l(x) tree[x].L#define r(x) tree[x].Rusing namespace std;const int maxn = 1e5+1000;struct Node{ int L,R,val;}tree[maxn*40];int root[maxn];vector<int> E[maxn];int a[maxn];int rk[maxn];int pos[maxn];int st[maxn][21];int dep[maxn];int cnt,m,n;int lastans=0;void input(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++){ scanf("%d",a+i); rk[i]=i; } for (int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); E[u].push_back(v); E[v].push_back(u); }}bool cmp(int x,int y){ return a[x]<a[y];}int build (int l,int r){ int k = cnt++; tree[k].val =0; if (l==r)return k; int mid = l+r >>1; tree[k].L = build(l,mid); tree[k].R = build (mid+1,r); return k;}int update(int P,int l,int r,int pos,int del){ int k = cnt++; tree[k].val = tree[P].val+del; if (l==r) return k; int mid = l+r >>1; if (pos<=mid){ tree[k].L = update(tree[P].L,l,mid,pos,del); tree[k].R = tree[P].R; }else{ tree[k].L = tree[P].L; tree[k].R = update(tree[P].R,mid+1,r,pos,del); } return k;}void dfs(int node,int father){ root[node] = update(root[father],1,n,pos[node],1); st[node][0] =father; dep[node] = dep[father]+1; for (int i=1;i<=19;i++){ st[node][i] = st[st[node][i-1]][i-1]; if (!st[node][i]){ break; } } for (vector<int>::iterator it = E[node].begin();it!=E[node].end();++it){ int v = *it; if (v==father)continue; dfs(v,node); }}void presolve(){ sort(rk+1,rk+1+n,cmp); for (int i=1;i<=n;i++){ pos[rk[i]] =i; } root[0] = build(1,n); dfs(1,0);}int lca(int u,int v){ if (dep[u]<dep[v]){ swap(u,v); } for (int i=19;i>=0;i--){ if (dep[st[u][i]]>=dep[v]){ u = st[u][i]; } } if (u==v){ return u; } for (int i=19;i>=0;i--){ if (st[u][i]!=st[v][i]){ u = st[u][i]; v = st[v][i]; } } return st[u][0];}int query_kth(int rtx,int rty,int anc,int fanc,int l,int r,int k){ if (l==r)return l; int mid = l+r>>1; int temp = tree[l(rtx)].val+tree[l(rty)].val-tree[l(anc)].val-tree[l(fanc)].val; if (temp>=k)return query_kth(tree[rtx].L,tree[rty].L,tree[anc].L,tree[fanc].L,l,mid,k); else return query_kth(tree[rtx].R,tree[rty].R,tree[anc].R,tree[fanc].R,mid+1,r,k-temp);}int query(int x,int y,int k){ int anc = lca(x,y);// printf("x=%d y=%d anc =%d ",x,y,anc); int tmp=query_kth(root[x],root[y],root[anc],root[st[anc][0]],1,n,k);// cout<<tmp<<endl; return a[rk[tmp]];}void solve(){ while (m--){ int x,y,k; scanf("%d%d%d",&x,&y,&k); x =x^lastans; lastans = query(x,y,k); printf("%d",lastans); if (m){ printf("\n"); } }}int main(){ input(); presolve(); solve(); return 0;}
阅读全文
0 0
- BZOJ 2588 & SPOJ 10628:树上主席树
- bzoj 2588 树上主席树
- 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
- BZOJ 2588 Spoj 10628. Count on a tree 主席树
- bzoj 2588 Spoj 10628 Count on a tree 树链剖分 主席树
- Bzoj 1803 spoj qtree3 主席树
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- SPOJ COT 树上第K大(LCA+主席树)
- SPOJ COT(树上k大,主席树+LCA)
- Spoj 10628. Count on a tree 树上主席树
- SPOJ COT 主席树+LCA(树上第k大)
- SPOJ Count on a tree(lca+主席树,树上主席树,好题)
- 【BZOJ 2588】Count on a tree 【树上路径第K大】【LCA+主席树】
- ES6(六: 函数扩展)(默认值,rest参数,扩展运算符)
- 第十二章 动态内存
- WPF and Silverlight 学习笔记(七):WPF布局管理之StackPanel、WrapPanel、DockPanel
- Jquery中AJAX参数详细介绍
- 图论中的双射
- BZOJ 2588 & SPOJ 10628:树上主席树
- Qt图片与Base64之间的编解码
- [Python]网络爬虫(二):利用urllib2通过指定的URL抓取网页内容
- java版云笔记(九)之动态sql
- 校招准备系列:每天一道算法题(12)-从尾到头打印链表
- linux 系统管理命令
- java学习笔记--数组
- Selenium3+Python3+PhantomJS配置及测试解析
- 2-3 jdk安装