HYSBZ-2588- Count on a tree (主席树)
2017-09-07 18:56
155 查看
Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit:128 MBSubmit: 7148 Solved: 1739
[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 5105 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
28
9
105
7
HINT
HINT:N,M<=100000
暴力自重。。。
中文题面就不讲意思了;
思路:这题就是找树上一条链上的第k小值,所以把每个点到根节点这些链建主席树,然后会发现u,v两个节点之间的链,在最后利用主席书计算的时候,主席树上记录的值等于u->root(根)这条链加上v->root减去lca[u,v]->root减去fa[lca[u,v]]->root,画个图想一下就懂了,这题就是在树上建主席树 ,算个入门题把;主席树刚学几天,写的时候写了个错误wa了好多发~~~这题求lca我是用树链剖分求的,倍增法还不会,并且感觉树链剖分求lca很好理解;
AC代码:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define maxn 100010 using namespace std; int n,m; int arr[maxn],b[maxn]; int dep[maxn],son[maxn],sz[maxn],fa[maxn],id[maxn],top[maxn],head[maxn];//树链剖分里面的一些数组 int tot,num,cnt,_sz; int root[maxn*35],lson[maxn*35],rson[maxn*35],sum[maxn*35];//根,左儿子,右儿子,记录数字个数 struct Edge{int to,next;}edge[maxn*2]; void add_edge(int u,int v)//相当于建题目给的图 { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void add_tree(int &rot,int pre,int id,int l,int r)//建当前点到root的主席树,由它的父亲得到 { rot=++cnt;//动态申请一个点 sum[rot]=sum[pre]+1;//数字的个数加1 lson[rot]=lson[pre];//左右儿子直接继承父亲的 rson[rot]=rson[pre]; if(l==r) return; int mid=(l+r)>>1; if(id<=mid) add_tree(lson[rot],lson[pre],id,l,mid); else add_tree(rson[rot],rson[pre],id,mid+1,r); } //树链剖分部分~~~~~ void dfs1(int u,int f,int deep) { son[u]=0;sz[u]=1; fa[u]=f;dep[u]=deep; add_tree(root[u],root[f],arr[u],1,_sz); for(int i=head[u];i!=-1;i=edge[i].next) { int ff=edge[i].to; if(ff==fa[u]) continue; dfs1(ff,u,deep+1); sz[u]+=sz[ff]; if(sz[son[u]]<sz[ff]) son[u]=ff; } } void dfs2(int u,int tp) { top[u]=tp; id[u]=++num; if(son[u]) dfs2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next){ int ff=edge[i].to; if(ff==fa[u]||ff==son[u]) continue; dfs2(ff,ff); } } int LCA(int u,int v) { while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) v=fa[top[v]]; else u=fa[top[u]]; } return dep[u]<dep[v]?u:v; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~ int query(int u,int v,int lca,int flca,int l,int r,int k) { if(l==r) return b[l]; int tmp=sum[lson[u]]+sum[lson[v]]-sum[lson[lca]]-sum[lson[flca]]; int mid=(l+r)>>1; if(tmp>=k) return query(lson[u],lson[v],lson[lca],lson[flca],l,mid,k); else return query(rson[u],rson[v],rson[lca],rson[flca],mid+1,r,k-tmp); } void init() { tot=num=cnt=0; memset(head,-1,sizeof(head)); } int main() { while(~scanf("%d%d",&n,&m)) { init(); for(int i=1;i<=n;i++) scanf("%d",&arr[i]),b[i]=arr[i]; sort(b+1,b+n+1); _sz=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) arr[i]=lower_bound(b+1,b+_sz+1,arr[i])-b;//在这里犯了个错误,b数组去重后数组个数变成了_sz个,开始写的b+n+1,结果错了几发 int x,y; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add_edge(x,y); add_edge(y,x); } dfs1(1,0,1); dfs2(1,1); int last=0; for(int i=1;i<=m;i++) { int u,v,k; scanf("%d%d%d",&u,&v,&k); u=u^last; int lca=LCA(u,v); last=query(root[u],root[v],root[lca],root[fa[lca]],1,_sz,k); printf("%d",last); if(i!=m) printf("\n");//格式注意一下 } } return 0; }
相关文章推荐
- BZOJ2588 Count on a tree <DFS序+LCA+值域主席树>
- [BZOJ2588]Count on a tree(可持久化权值线段树|主席树)
- bzoj 2588: Spoj 10628. Count on a tree LCA+主席树
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA
- BZOJ 2588 Count on a tree 主席树
- [主席树] BZOJ 2588 Spoj 10628. Count on a tree
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- BZOJ 2588 Spoj 10628. Count on a tree 主席树
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- bzoj2588: Spoj 10628. Count on a tree 主席树+dfs序
- bzoj2588 Spoj 10628. Count on a tree【主席树+lca】
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
- bzoj2588: Spoj 10628. Count on a tree(树上第k大)(主席树)
- BZOJ.2588.Count on a tree(主席树 静态树上第k小)
- 洛谷 P2633 Count on a tree[bzoj2588](倍增lca+主席树)
- BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
- BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树
- 主席树初探--BZOJ2588: Spoj 10628. Count on a tree
- [bzoj2588][主席树]Count on a tree