bzoj2588: Spoj 10628. Count on a tree
2016-04-11 22:36
495 查看
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2588
题意:中文题。
分析:树上建可持久化线段树,从父亲那继承。查询的时候减去lca和lca的父亲两个前缀即可。详见代码。O(nlogn+mlogn) PS:注意输出格式!
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=100100; const int MAX=100000000; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const ll INF=10000000010; typedef double db; typedef unsigned long long ull; int a ,b ,c ; int tot,u ,v[2*N],pre[2*N]; void add(int x,int y) { v[tot]=y;pre[tot]=u[x];u[x]=tot++; } int n,de ,fa [20]; int sz,root ,ls[20*N],rs[20*N],sum[20*N]; void build(int l,int r,int x,int &y,int z) { y=++sz;sum[y]=sum[x]+1; if (l==r) return ; int mid=(l+r)>>1; ls[y]=ls[x];rs[y]=rs[x]; if (z<=mid) build(l,mid,ls[x],ls[y],z); else build(mid+1,r,rs[x],rs[y],z); } void dfs(int x,int y) { de[x]=de[y]+1;fa[x][0]=y; build(1,n,root[y],root[x],a[x]); for (int i=1;i<=20;i++) if (de[x]>1<<i) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=u[x];i!=-1;i=pre[i]) if (v[i]!=y) dfs(v[i],x); } int getlca(int x,int y) { if (de[x]<de[y]) { x^=y;y^=x;x^=y; } for (int i=20;i>=0;i--) if (de[x]-(1<<i)>=de[y]) x=fa[x][i]; if (x==y) return x; for (int i=20;i>=0;i--) if (de[x]>1<<i&&fa[x][i]!=fa[y][i]) { x=fa[x][i];y=fa[y][i]; } return fa[x][0]; } int get_k(int l,int r,int x,int y,int z,int w,int k) { if (l==r) return l; int mid=(l+r)>>1; if (sum[ls[z]]+sum[ls[w]]-sum[ls[x]]-sum[ls[y]]>=k) return get_k(l,mid,ls[x],ls[y],ls[z],ls[w],k); else return get_k(mid+1,r,rs[x],rs[y],rs[z],rs[w],k-(sum[ls[z]]+sum[ls[w]]-sum[ls[x]]-sum[ls[y]])); } int main() { int i,m,k,x,y,w,lca,ans=0; scanf("%d%d", &n, &m); for (i=1;i<=n;i++) { scanf("%d", &a[i]);b[i]=a[i]; } sort(b+1,b+n+1); k=unique(b+1,b+n+1)-(b+1); for (i=1;i<=n;i++) { w=lower_bound(b+1,b+k+1,a[i])-b; c[w]=a[i];a[i]=w; } tot=0;memset(u,-1,sizeof(u)); for (i=1;i<n;i++) { scanf("%d%d", &x, &y); add(x,y);add(y,x); } dfs(1,0); while (m--) { scanf("%d%d%d", &x, &y, &k); x^=ans;lca=getlca(x,y); ans=c[get_k(1,n,root[lca],root[fa[lca][0]],root[x],root[y],k)]; printf("%d", ans); if (m) printf("\n"); } return 0; }
相关文章推荐
- C#贪吃蛇(WPF版)
- 自定义Dialog的简单实现
- C语言函数
- C++实现读取特定路径下文件夹及文件名的方法
- HTTP Keep-Alive详解
- 设计模式六大原则(5):迪米特法则
- JQuery和UpdatePannel的问题
- Windows内核读书笔记——SEH结构化异常处理
- 在Ubuntu中清理Network下Connect to Server的入口
- java面试题------40个Java集合面试问题和答案
- Windows驱动开发(3) - 内核模式下的字符串操作
- 网络流的征程——Ford-Fulkerson算法
- java面试题------40个Java集合面试问题和答案
- Android Connectivity分析(1)- ConnectivityManager
- OS中常用的调度算法总结
- Secure CRT键盘自我习惯
- shiro 的role 角色权限控制简单demo论述
- identity natiive assigned
- andorid 手机外部储存
- ob_get_contents()函数及与其相关几个函数的用法