HDU 4836 —— The Query on the Tree(线段树+LCA)
来源:互联网 发布:php redis watch 编辑:程序博客网 时间:2024/06/05 06:49
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4836
下午百度之星复赛里最简单的一题,虽然我还是1个小时才AC的,呃,下午果断被虐粗翔。
本题磨了1个小时才过,第1题还是很猥琐地用了随机数过的(真不知道怎么做)。
回到这题来,其实也不知道大牛们怎么做的,我只能用线段树+LCA搞了。
首先考虑根不改变的情况,那么我们可以将每个结点映射到线段树上去,让每个点对应的子树的点都落在某个连续区间上;
具体是在dfs的时候,用id来表示当前已经映射到线段树的编号,初始为0,进入某个结点X,令left[X]=right[X]=++id,然后继续dfs,对于X每个子节点j,dfs完了顺便更新right[X]=max(right[X], right[j]),这样在所有子节点遍历完的情况下,left[X]到right[X]就刚好是以X为根的子树的区间。在纸上模拟下就明白了。
然后对于查询和点更新就是个经典的线段树问题了。
比较麻烦的是根被改变的情况,假设我们现在要查询以X为根的子树的和,分析下当前根是root时与原先的不同。如果root原来就是X的祖先了,那么答案跟原来是一样的,再往下想其实就是只要root需要经过X原先某个祖先到达X的话,答案应该都一样的,所以这个好办。
而如果X刚好就是root,那么答案就是整棵树的和,也好处理。
剩下的就是原来X是root的祖先,我们假设X经过它的某个子节点Y到达root,那么很明显当前X的子树和,应该是整棵树的值减去原来Y对应的子树的和。因为X-Y这条边是root进行dfs到达X的最后一条边,换句话说这条边就把是不是X的子树的点分隔开了。
分析到这里问题就好办了,对于查询X,求出它们的最近公共祖先V,再进行判断即可。
#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;#define lson o<<1#define rson (o<<1)|1#define N 10001#define pb push_backvector<int> V[N];int t, ct, n;int left[N], right[N], val[N], v2[N];int s[N<<2], l[N<<2], r[N<<2];int id, root;bool f[N];int depth[N], parent[16][N];void dfs(int x){ left[x] = right[x] = ++id; v2[id] = val[x]; for(int i=0; i<V[x].size(); i++){ int j=V[x][i]; if(f[j]) continue; f[j]=1; depth[j] = depth[x]+1; parent[0][j] = x; dfs(j); right[x] = max(right[x], right[j]); }}void maintain(int o){ s[o] = s[lson]+s[rson];}void build(int o, int ll, int rr){ l[o]=ll; r[o]=rr; s[o]=0; if(ll<rr){ int m = (ll+rr)>>1; build(lson, ll, m); build(rson, m+1, rr); maintain(o); } else{ s[o] = v2[ll]; }}void update(int o, int p, int v){ if(l[o]==p && r[o]==p){ s[o]=v; return; } int m = (l[o]+r[o])>>1; if(p<=m) update(lson, p, v); else update(rson, p, v); maintain(o);}void init_lca(){ for(int k=0; k<15; k++){ for(int v=1; v<=n; v++){ if(parent[k][v]<0) parent[k+1][v]=-1; else parent[k+1][v] = parent[k][parent[k][v]]; } }}int lca(int u, int v){ if(depth[u]>depth[v]){ swap(u,v); } for(int k=0; k<16; k++){ if((depth[v]-depth[u])>>k & 1){ v = parent[k][v]; } } if(u==v) return u; for(int k=15; k>=0; k--){ if(parent[k][u]!=parent[k][v]){ u=parent[k][u]; v=parent[k][v]; } } return parent[0][u];}int query(int o, int ll, int rr){ if(l[o]==ll && r[o]==rr) return s[o]; int m = (l[o]+r[o])>>1; if(rr<=m) return query(lson, ll, rr); else if(ll>m) return query(rson, ll, rr); else return query(lson, ll, m)+query(rson, m+1, rr);}int query(int x){ if(x==root) return s[1]; int v = lca(root, x); if(v!=x){ return query(1, left[x], right[x]); } for(int i=0; i<V[x].size(); i++){ int j=V[x][i]; if(depth[j]<depth[x]) continue; v = lca(root, j); if(v==j){//找到前面所说的Y return s[1] - query(1, left[j], right[j]); } } return 0;}inline void in(int &x){ char c=getchar(); x=0; while(c<48 || c>57) c=getchar(); while(c>=48 && c<=57){ x = x*10+c-48; c = getchar(); }}int main(){ in(t); for(ct=1; ct<=t; ct++){ printf("Case #%d:\n", ct); in(n); for(int i=1; i<=n; i++) V[i].clear(); int x, y; for(int i=1; i<n; i++){ in(x); in(y); V[x].pb(y); V[y].pb(x); } for(int i=1; i<=n; i++){ in(val[i]); } memset(f,0,sizeof(f)); memset(parent,-1,sizeof(parent)); f[1]=1; id = 0; depth[1]=1; dfs(1); init_lca(); build(1, 1, n); int q; char op[10]; in(q); root=1; while(q--){ scanf("%s", op); in(x); if(op[0]=='Q'){ printf("%d\n", query(x)); } else if(op[0]=='C'){ in(y); update(1, left[x], y); } else{ root = x; } } } return 0;}
- HDU 4836 —— The Query on the Tree(线段树+LCA)
- 【HDU】4836 The Query on the Tree dfs+线段树
- HDU 4836 The Query on the Tree (欧拉序列,线段树,动态树)
- hdu 4836 The Query on the Tree(线段树or树状数组)
- HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树
- Hdu 4836 The Query on the Tree
- lca(HDU 4718,The LCIS on the Tree)
- hdu 4912Paths on the tree (LCA)
- HDU 4912 - Paths on the tree (LCA 贪心)
- HDU 4912 Paths on the tree (LCA+贪心)
- HDU 4912 Paths on the tree(LCA+贪心)
- HDU 4718 The LCIS on the Tree(树链剖分+线段树)
- hdu 4918 Query on the subtree (动态点分治+动态开点+线段树)
- 【HDU】4010 Query on The Trees 动态树之Link Cut Tree(LCT)
- HDU 4912 Paths on the tree LCA 排序贪心
- hdu 4912 Paths on the tree(lca+贪心)
- hdu 4912 Paths on the tree lca+贪心
- hdu 4912 Paths on the tree LCA + 贪心
- java的awt和swing有什么不同
- Google开源基于Deep Learning的word2vec工具
- “生产者-消费者”实验
- java类集
- Web Worker进行数据交换
- HDU 4836 —— The Query on the Tree(线段树+LCA)
- J2EE规范
- 百度之星2010 复赛2 购物搜索调研
- C#程序中从数据库取数据时需注意数据类型之间的对应,int16\int32\int64
- DirectX (9) 纹理映射
- 大话设计模式——工厂方法模式(C++计算器修改)
- spring(2)-cxf
- MCA缓存应用加速平台
- php soap setheader