2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
来源:互联网 发布:盖伊福克斯面具淘宝 编辑:程序博客网 时间:2024/05/22 06:19
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 7448 Solved: 1815
[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
分析:求树上的第K大值,主席树题,但是怎么建立主席树,这里可以不用轻重链剖分,我们只需要记录每个节点到根节点的路径信息(用权值线段树)统计,结果就是root【L】+root【R】-root【lca(L,R)】-root【fa【lca(L,R) 】】;
有一个需要注意的点就是题上给的边是无向边。还有就是求LCA需要用ST算法优化。
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <queue>#define mem(p,k) memset(p,k,sizeof(p));#define pb push_back#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define inf 0x3f3f3f3f//#define ll long longusing namespace std;const int N=100010 ;int n,m,len,tot;int root[N],dep[N];long long a[N];int ls[N*30],rs[N*30],s[N*30];bool bk[N];int tot2,dp[N<<1][20],R[N<<1],first[N],ver[N<<1],fa[N];vector<long long> vec;vector<int> edg[N];int edg2[N];int Hash(long long k){ return lower_bound(vec.begin(),vec.end(),k)-vec.begin()+1;}void update(int k,int val,int pre,int &now,int l,int r){ now=++tot; ls[now]=ls[pre]; rs[now]=rs[pre]; s[now]=s[pre]+val; if(l==r)return; int m=(l+r)>>1; if(k<=m)update(k,val,ls[pre],ls[now],l,m); else update(k,val,rs[pre],rs[now],m+1,r);}void build(int d,int pre,int now){ update(Hash(a[now]),1,root[pre],root[now],1,len); dep[now]=d; bk[now]=1; ver[++tot2]=now,first[now]=tot2;R[tot2]=d;fa[now]=pre; int l=edg[now].size(); if(!l)return; for(int i=0;i<l;i++){ if(bk[edg[now][i]])continue; build(d+1,now,edg[now][i]); ver[++tot2]=now,R[tot2]=d; }}void ST(int n){ for(int i=1;i<=n;i++) dp[i][0] = i; for(int j=1;(1<<j)<=n;j++) { for(int i=1;i+(1<<j)-1<=n;i++) { int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1]; dp[i][j] = R[a]<R[b]?a:b; } }}int RMQ(int l,int r){ int k=log(r-l+1)/log(2); int a = dp[l][k], b = dp[r-(1<<k)+1][k]; return R[a]<R[b]?a:b;}int finlca(int l,int r){ int x = first[l] , y = first[r]; if(x > y) swap(x,y); int res = RMQ(x,y); return ver[res];}long long Query(int l,int r,int k,int f){ int ll=1,rr=len,cur=Hash(a[f]); l=root[l],r=root[r],f=root[f]; while(ll<=rr){ if(ll==rr){ return vec[ll-1]; } int m=(ll+rr)>>1; int sum=s[ls[l]]+s[ls[r]]-2*s[ls[f]]+(cur<=m && cur>=ll?1:0); if(k<=sum){ rr=m; l=ls[l]; r=ls[r]; f=ls[f]; } else{ ll=m+1; k-=sum; l=rs[l]; r=rs[r]; f=rs[f]; } }}int main(){ int l,r,k; scanf("%d%d",&n,&m); vec.clear(); mem(ls,0); mem(rs,0); mem(s,0); mem(root,0); tot2=0; for(int i=1;i<=n;i++){ scanf("%lld",a+i); vec.pb(a[i]); } sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end()); len=vec.size(); for(int i=0;i<=n;i++)edg[i].clear(); mem(edg2,0); mem(bk,0); for(int i=1;i<n;i++){ scanf("%d%d",&l,&r); edg[l].pb(r); edg[r].pb(l); } tot=0; build(1,0,1); ST(tot2); long long last=0; while(m--){ scanf("%d%d%d",&l,&r,&k); l^=last; printf("%lld",last=Query(l,r,k,finlca(l,r))); if(m)printf("\n"); } return 0;}
阅读全文
0 0
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)
- 【BZOJ 2588】 Spoj 10628. Count on a tree|树上K大|树链剖分|主席树
- 【BZOJ 2588】Count on a tree 【树上路径第K大】【LCA+主席树】
- SPOJ Count on a tree(树上第K大)
- bzoj2588 Count on a tree(树上建主席树求路径第k大)
- SPOJ COTCount on a tree(树上路径第k小 主席树)
- SPOJ COTCount on a tree 树上第k大(主席树)
- SPOJ Count on a tree 树上第k大。
- SPOJ COT Count on a tree (树上k大 主席树模板)
- Spoj 10628. Count on a tree 树上主席树
- bzoj 2588: Spoj 10628. Count on a tree(树上主席树)
- 【BZOJ 2588】Spoj 10628. Count on a tree 主席树+树上差分
- BZOJ BZOJ 2588: Spoj 10628. Count on a tree 树上主席树
- SPOJ COT Count on a tree 树上第k小
- 2588: Spoj 10628. Count on a tree 主席树+LCA
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- [主席树] BZOJ 2588 Spoj 10628. Count on a tree
- NOIP模拟10.17
- Spring:享受IOC与AOP之美
- java中的getParentFile
- Nginx与PHP(FastCGI)的安装、配置和优化
- MySQL的模糊查询时用中文查不出来解决
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- 实验4:栈和队列的基本操作实现及其应用之《链队列》
- HashMap底层详解
- HDU-2200
- Springmvc工作流程图
- OO设计思想->继承与组合的区别
- 去掉服务器返回到浏览器json数据中的null
- Java Platform SE binary已停止运行 Can't load AMD 64-bit.dll on a IA 32-bit platform错误
- 1055: 背包1(填满型01背包 &降维)