The Query on the Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 57    Accepted Submission(s): 20

Problem Description
度度熊近期沉迷在和树有关的游戏了。他一直觉得树是最奇妙的数据结构。

一天他遇到这样一个问题:
  有一棵树,树的每一个点有点权,每次有三种操作:
  1. Query x 表示查询以x为根的子树的权值和。

  2. Change x y 表示把x点的权值改为y(0<=y<=100)。

  3. Root x 表示把x变为根。

  如今度度熊想请更聪明的你帮助解决问题。

Input
第一行为数据组数T(1 <= T <= 100)
  每组数据第一行为N(1<= N <= 10000),表示树的节点数。
  后面N-1行每行有两个数x,y 。表示x,y之间有一条边 1<=x,y<=N。初始时树是以1号节点为根节点。

  之后的一行为N个数表示这N个点的点权(点权的范围是0到100)。

  然后为整数Q(Q<=1000)为操作次数。

  之后的Q行为描写叙述中的三种操作。

Output
对于第k组输入数据。第一行输出Case #k 接下来对于每一个”Query x”操作。输出以x为根的子数和。
Sample Input
2 5 1 2 1 3 3 4 3 5 1 2 3 4 5 5 Query 1 Change 3 10 Query 1 Root 4 Query 3 8 1 2 1 3 3 4 4 5 5 6 5 7 4 8 1 2 3 4 5 6 7 8 5 Query 1 Query 3 Root 5 Query 3 Query 1
Sample Output
Case #1: 15 22 18 Case #2: 36 33 6 3

题意:天朝文字不解释

题解:我先将树的点以1为根转换成一个数组并记录每一个点子树的范围。就是类似lca的那个树转数组一样,将一个点分成2个点,dfs的时候到达结点时候生成一个点值为结点本身的值,离开结点生成一个点值为0,然后保存其这2个点的位置,那么求某个点的子树和就变成了求该个区间和了,区间和操作和改变某个点的值都能够用线段树or树状数组维护。当须要更改根的时候仅记录root。我们的树始终以1为根,不作其他改变。那么查询操作。若root不是x的子树的结点,x的子树和就是x相应的区间和;若root是x的子树的结点。就要找出root是x哪个儿子的子树,然后x的子树和就是全部数的值减去那个包括root结点的子树的和。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
struct node{int y,next;
}e[80008];
int head[80008],val[80008],tree[80008];
int sta[80008],ssta[80008],fin[80008];
int a[80008],n,all;
vector<int>v[80008];
void add(int x,int y)
{e[all].next=head[x];e[all].y=y;head[x]=all++;
}
void dfs(int x,int &cou,int fa)
{a[cou]=val[x];sta[x]=cou++;for(int i=head[x];i!=-1;i=e[i].next){if(fa==e[i].y) continue;dfs(e[i].y,cou,x);v[x].push_back(sta[e[i].y]);}fin[x]=cou++;
}
void build(int l,int r,int pos)
{int mid=(l+r)>>1;if(l==r){ tree[pos]=a[l]; return; }build(l,mid,pos<<1);build(mid+1,r,pos<<1|1);tree[pos]=tree[pos<<1]+tree[pos<<1|1];
}
void updata(int l,int r,int pos,int x,int y)
{int mid=(l+r)>>1;if(l==r){ tree[pos]=y; return; }if(x<=mid) updata(l,mid,pos<<1,x,y);else updata(mid+1,r,pos<<1|1,x,y);tree[pos]=tree[pos<<1]+tree[pos<<1|1];
}
int query(int l,int r,int pos,int templ,int tempr)
{int mid=(l+r)>>1;if(templ<=l&&r<=tempr) return tree[pos];if(tempr<=mid) return query(l,mid,pos<<1,templ,tempr);else if(templ>mid) return query(mid+1,r,pos<<1|1,templ,tempr);return query(l,mid,pos<<1,templ,mid)+query(mid+1,r,pos<<1|1,mid+1,tempr);
}
int main()
{int t,x,y,m,cas=1;char s[18];scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));memset(a,0,sizeof(a));all=0;scanf("%d",&n);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);add(x,y),add(y,x);}int cou=1;for(int i=1;i<=n;i++){scanf("%d",val+i);v[i].clear();}dfs(1,cou,-1);for(int i=1;i<=n;i++){ssta[sta[i]]=i;if(v[i].size()<=0) continue;sort(v[i].begin(),v[i].end());}build(1,cou-1,1);scanf("%d",&m);int root=1;printf("Case #%d:\n",cas++);while(m--){scanf("%s",s);if(s[0]=='C'){scanf("%d%d",&x,&y);updata(1,cou-1,1,sta[x],y);}else if(s[0]=='R') scanf("%d",&root);else{scanf("%d",&x);if(x==root) printf("%d\n",tree[1]);else if(sta[x]<sta[root]&&fin[root]<fin[x]){int temp=upper_bound(v[x].begin(),v[x].end(),sta[root]) - v[x].begin();temp=ssta[v[x][temp-1]];printf("%d\n",tree[1]-query(1,cou-1,1,sta[temp],fin[temp]));}else printf("%d\n",query(1,cou-1,1,sta[x],fin[x]));}}}return 0;
}

hdu 4836 The Query on the Tree(线段树or树状数组)相关推荐

  1. HDU 1325POJ 1308 Is it A tree ? [并查集+树判定]

    题目链接 poj hdu Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...

  2. HDU - 3804 Query on a tree(主席树维护最大值+离散化)

    题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...

  3. HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...

  4. SPOJ 375. Query on a tree (树链剖分)

    题目链接: http://www.spoj.com/problems/QTREE/ 375. Query on a tree Problem code: QTREE You are given a t ...

  5. hdu 4417(线段树OR树状数组)

    题意:输入一个长度为n的序列,然后m个询问,询问区间[a,b]中比h小的数的个数. 思路:树状数组或线段树离线处理. 树状数组1 View Code 1 #include<cstdio> ...

  6. HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)

    题目链接:点击查看 题目大意:给出一个二维平面坐标系,需要完成四种操作: 0:删除所有点 1 xycx\ y\ cx y c:在点 (x,y)(x,y)(x,y) 处添加颜色 ccc 2 xy1y2x ...

  7. HDU - 6393 Traffic Network in Numazu(线段树+LCA+树链剖分+并查集)

    题目链接:点击查看 题目大意:给出一个由n个点和n条边组成的图,每条边都有权值,题目保证图是连通的,然后给出m个询问,每次询问分为两种形式: 0 x y:将第x条边的权值修改为y 1 x y:查询x- ...

  8. XXI Open Cup. Grand Prix of Korea I. Query On A Tree 17 树剖 + 二分 + 树带权重心

    传送门 文章目录 题意: 思路: 题意: 给你一棵树,每棵树初始权值都为000,现在给你两个操作: (1)(1)(1)将uuu的子树权值全部加111. (2)(2)(2)将(u,v)(u,v)(u,v ...

  9. [BZOJ1095][ZJOI2007]捉迷藏 Query on a tree IV(树链剖分)

    首先,我们求出树的重链,然后对于每一条链,建一颗线段树 树大概长这样: (其中用红边连起来的是一条条重链) 在线段树上,我们维护: Opt(u):经过 u节点代表的链的其中一段 的两个白点间的最长路径 ...

最新文章

  1. Linux MTD系统剖析【转】
  2. Cpp / __builtin_expect 说明
  3. sql sever 中如何查看某个表的索引_查看执行计划:explain的type
  4. C# FileSystemWatcher 在监控文件夹和文件时的用法
  5. swing皮肤包 substance
  6. 本周四直播丨Oracle中为什么没有double write?那支持原子写吗?
  7. 51CTO‘s Bug?
  8. Java 算法 超级玛丽
  9. hdu 1524 A Chess Game
  10. 9-n个人中选k个人的选择方法种类
  11. php markdown 电子书_PHP Markdown转PDF解决方案
  12. str python3_python3.4.3如何转换str字符串?
  13. 【docker系列】docker深入浅出之安装Nginx+PHP+MySQL
  14. 使用微软官方升级工具升级win11的方法
  15. 漂亮有创意的思维导图模板下载教程,教你思维导图怎么画
  16. 如何编写好的软件设计文档
  17. FPS游戏(UE4,U3D引擎)方框绘制,骨骼透视,BT功能的原理 和反外挂策略
  18. 微信小程序-微信支付
  19. 大数据技术之_13_Azkaban学习_Azkaban(阿兹卡班)介绍 + Azkaban 安装部署 + Azkaban 实战
  20. 小白也可以开发闲鱼自动化工具(自动找爆款)

热门文章

  1. 注册cn域名应该注意些什么
  2. oracle常用网址
  3. Web应用中避免Form重复提交的三种方案
  4. VMware 修复 Workstation、Fusion 和 ESXi中的多个漏洞
  5. Kramdown 配置不当引发 GitHub Pages 多个 RCE,得 $2.5万($6.1万系列之二)
  6. ZDI 公布2020年 Pwn2Own 东京赛规则和奖金
  7. Linux入门之VIM快捷使用
  8. Android自定义View初步
  9. 调整自己,必须调整自己了
  10. POJ 1797 Heavy Transportation 最短路变形(dijkstra算法)