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 4836 The Query on the Tree lca || 欧拉序列 || 动态树

    lca的做法还是非常明显的.简单粗暴, 只是不是正解.假设树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的.预计就是放在splay上剖分一 ...

  2. 2017广西邀请赛 Query on A Tree (可持续化字典树)

    Query on A Tree 时间限制: 8 Sec  内存限制: 512 MB提交: 15  解决: 3[提交][状态][讨论版] 题目描述 Monkey A lives on a tree. H ...

  3. 【HDU 6191】Query on A Tree 【可持久化字典树】

    题目 给出一棵有n个结点的树,树根是1,每个结点给出一个value.然后给出q个询问,每个询问给出两个整数u和x,你要在以u结点为根的子树中找出一个结点v,使得val[v] xor x最大, 并输出这 ...

  4. HDU - 6191 Query on A Tree (可持久化字典树/字典树合并)

    题目链接 题意:有一棵树,树根为1,树上的每个结点都有一个数字x.给出Q组询问,每组询问有两个值u,x,代表询问以结点u为根的子树中的某一个数与x的最大异或值. 解法一:dfs序+可持久化字典树.看到 ...

  5. SPOJ 1487 Query on a tree III(划分树)

    题目链接:http://www.spoj.com/problems/PT07J/ 题意:给出一个有根树,1为根节点,每个节点有权值.若干询问,询问以u为根的子树中权值第K小的节点编号. 思路:DFS一 ...

  6. 「SPOJ1487」Query on a tree III

    「SPOJ1487」Query on a tree III 传送门 把树的 \(\text{dfs}\) 序抠出来,子树的节点的编号位于一段连续区间,然后直接上建主席树区间第 \(k\) 大即可. 参 ...

  7. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  8. HDU 3333 Turing Tree 线段树+离线处理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...

  9. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

随机推荐

  1. AngularJS之Service4

    AngularJS之Service(四)   前言 前面我们讲了控制器.过滤器以及指令,这一节我们来讲讲重大内容之一服务和其中涉及到的工厂. 话题 AngularJS中服务可以说是和DI紧密联系在一起 ...

  2. SilkTest Q&A 8

    Q72.如何在一个testplan中运行所有的testcase? A72. 1.打开testplan 2.点击Run/Run All Tests菜单,SilkTest开始执行testplan中所有的t ...

  3. wp实例开发精品文章源码推荐

    WP8 启动媒体应用         这个示例演示了如何选择正确的msAudioCategory类别的音像(AV)流来配置它作为一个音频播放流.具体地说,这个示例执行以下操作:启动一个媒体应用与“媒体 ...

  4. hdu3986Harry Potter and the Final Battle

    给你一个无向图,然后找出当中的最短路, 除去最短路中的随意一条边,看最糟糕的情况下, 新的图中,第一个点到末点的最短路长度是多少. 我的做法是: 首先找出最短路,然后记录路径, 再一条一条边的删, 删 ...

  5. c/c++ 动态申请数组

    new和delete运算符用于动态分配和撤销内存的运算符 new使用方法: 1.     开辟单变量地址空间 1)new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.in ...

  6. Qt之启动外部程序(使用参数很全面,还使用了setProcessChannelMode)

    简述 QProcess可以用来启动外部程序,并与它们交互. 要启动一个进程,通过调用start()来进行,参数包含程序的名称和命令行参数,参数作为一个QStringList的单个字符串. 另外,也可以 ...

  7. 打开excel2007文档时显示“excel无法打开文件~$book.xltm”

    此问题的出现是因为意外情况导致Excel临时文件没有删掉,把C:\Program Files\Microsoft Office\Office12\XLSTART里面的临时文件“~$book”给删除就好 ...

  8. KVM 实现机制

    1.1.    KVM简介 KVM是一个基于Linux内核的虚拟机,它属于完全虚拟化范畴,从Linux-2.6.20开始被包含在Linux内核中.KVM基于x86硬件虚拟化技术,它的运行要求Intel ...

  9. hash应用以及vector的使用简介:POJ 3349 Snowflake Snow Snowflakes

    今天学的hash.说实话还没怎么搞懂,明天有时间把知识点总结写了,今天就小小的写个结题报告吧! 题意: 在n (n<100000)个雪花中判断是否存在两片完全相同的雪花,每片雪花有6个角,每个角 ...

  10. GitHub上最受欢迎的Android开源项目TOP20

    以下这些开源项目都是从GitHub上筛选的,我强烈推荐android程序源代码有时间的时候自己在上面淘淘,或许能发现自己须要的开源程序. 了解开源项目有两个优点: 1.借鉴代码,一般来说.火爆的开源项 ...