一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

树剖模板。

 #include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std; const int INF=1e9+,NN=,MM=1e5+; int n,m,sz;
int a[NN],deep[NN],size[NN],fa[NN],pos[NN],bl[NN];
int cnt,head[NN],next[MM],rea[MM];
struct Node
{
int l,r,mx,sum;
}tree[MM]; void add(int u,int v)
{
cnt++;
next[cnt]=head[u];
head[u]=cnt;
rea[cnt]=v;
}
void dfs_init(int x)
{
size[x]=;
for (int i=head[x];i!=-;i=next[i])
{
int v=rea[i];
if (v==fa[x]) continue;
deep[v]=deep[x]+;
fa[v]=x;
dfs_init(v);
size[x]+=size[v];
}
}
void dfs_make(int x,int chain)//chain表示重链首的编号
{
int k=;//找重链
sz++;
pos[x]=sz;//分配编号;
bl[x]=chain;
for (int i=head[x];i!=-;i=next[i])
{
int v=rea[i];
if (deep[v]>deep[x]&&size[v]>size[k]) k=v;
}
if (k==) return;
dfs_make(k,chain);
for (int i=head[x];i!=-;i=next[i])
{
int v=rea[i];
if (deep[v]>deep[x]&&k!=v) dfs_make(v,v);
}
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if (l==r) return;
int mid=(l+r)>>;
build(k<<,l,mid),build((k<<)+,mid+,r);
}
void change(int k,int x,int y)
{
int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
if (l==r){tree[k].sum=tree[k].mx=y;return;}
if (x<=mid) change(k<<,x,y);
else change(k<<|,x,y);
tree[k].sum=tree[k<<].sum+tree[k<<|].sum;
tree[k].mx=max(tree[k<<].mx,tree[k<<|].mx);
}
int query_sum(int k,int x,int y)
{
int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
if (l==x&&r==y) return tree[k].sum;
if (y<=mid) return query_sum(k<<,x,y);
else if (x>mid) return query_sum(k<<|,x,y);
else return query_sum(k<<,x,mid)+query_sum(k<<|,mid+,y);
}
int query_max(int k,int x,int y)
{
int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
if (l==x&&y==r) return tree[k].mx;
if (y<=mid) return query_max(k<<,x,y);
else if (x>mid) return query_max(k<<|,x,y);
else return max(query_max(k<<,x,mid),query_max(k<<|,mid+,y));
}
int solve_sum(int x,int y)
{
int sum=;
while (bl[x]!=bl[y])//表示标记不同
{
if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
sum+=query_sum(,pos[bl[x]],pos[x]);
x=fa[bl[x]]; //跳完整条重链。
}
if (pos[x]>pos[y]) swap(x,y);
sum+=query_sum(,pos[x],pos[y]);
return sum;
}
int solve_max(int x,int y)
{
int mx=-INF;
while (bl[x]!=bl[y])
{
if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
mx=max(mx,query_max(,pos[bl[x]],pos[x]));
x=fa[bl[x]];
}
if (pos[x]>pos[y]) swap(x,y);
mx=max(mx,query_max(,pos[x],pos[y]));
return mx;
}
int main()
{
memset(head,-,sizeof(head));
scanf("%d",&n);
for (int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
for (int i=;i<=n;i++)
scanf("%d",&a[i]);
dfs_init();
dfs_make(,);
build(,,n);//建树。
for (int i=;i<=n;i++)
change(,pos[i],a[i]);
scanf("%d",&m);
char c[];
for (int i=;i<=m;i++)
{
int x,y;
scanf("%s%d%d",c,&x,&y);
if (c[]=='C')
{
a[x]=y;
change(,pos[x],y);
}
else
{
if (c[]=='M') printf("%d\n",solve_max(x,y));
else printf("%d\n",solve_sum(x,y));
}
}
}

bzoj1036 [ZJOI2008]树的统计的更多相关文章

  1. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  2. bzoj1036 [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 12646  Solved: 5085 [Subm ...

  3. bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

    [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

  4. bzoj千题计划124:bzoj1036: [ZJOI2008]树的统计Count

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分板子题 #include<cstdio> #include<iost ...

  5. BZOJ1036 [ZJOI2008]树的统计Count 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1036 题意概括 一个树,每个节点有一个权值.3种操作. 1:修改某一个节点的权值. 2:询问某两个 ...

  6. 【lct】bzoj1036 [ZJOI2008]树的统计Count

    题意:给你一棵树,点带权,支持三种操作:单点修改:询问链上和:询问链上max. 这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦): 先ChangeR ...

  7. BZOJ1036[ZJOI2008]树的统计Count 题解

    题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.有一些操作:1.把结点u的权值改为t:2.询问从点u到点v的路径上的节点的最大权值 3.询问从点u到点v的路径上的节点的权值和 ...

  8. bzoj1036 zjoi2008 树的统计 count

    填坑= =第一道裸树剖 #include<cstdio> #include<algorithm> #include<cstring> #include<cst ...

  9. [BZOJ1036] [ZJOI2008] 树的统计Count (LCT)

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

随机推荐

  1. P问题、NP问题、NPC问题

    看师兄们的论文经常说一句这是个NP难问题,所以采用另外一种方法来代替(比如凸松弛,把l0范数的问题松弛为l1范数的问题来求解).然后搜索了相关知识,也还是没看太懂,把一些理论知识先贴上来,希望以后再接 ...

  2. mysql 数据库安装步骤个人总结

    1.mysql-5.7.19-winx64.zip(此为免安装版,318兆左右,还有一种是安装版,380兆左右mysql-installer-community-5.7.19.0.msi)将此安装包解 ...

  3. 利用HTML5的window.postMessage实现跨域通信

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp77   HTML5的window.postMessage简述 postM ...

  4. none,hidden和opacity="0"设置元素不可见的区别

    none,hidden和opacity="0"均可设置元素为不可见的状态.其中none属于display的属性值,hidden属于visibility的属性值.使用none时元素不 ...

  5. Python 进程与线程小随笔

    Process 涉及模块:multiprocessing Process p = Process() p.start() p.join() from multiprocessing import Pr ...

  6. 【2017集美大学1412软工实践_助教博客】团队作业8——第二次项目冲刺(Beta阶段)

    题目 团队作业8: http://www.cnblogs.com/happyzm/p/6856179.html 团队作业8-1 beta冲刺计划 团队 新加入的成员,担当的角色,技术特点 下一阶段需要 ...

  7. 团队作业8——Beta 阶段冲刺3rd day

    一.当天站立式会议 二.每个人的工作 (1)昨天已完成的工作(具体在表格中) 添加了订单功能,并且对订单功能进行了测试 (2)今天计划完成的工作(具体如下) 添加支付功能 (3) 工作中遇到的困难(在 ...

  8. 团队作业4——第一次项目冲刺(Alpha版本)2017.4.25

    在下午的1,2节软件课程结束后,我们teamworkers全体队员在禹州楼302利用课间时间进行约15分钟的短暂会议,会议的内容为阐述昨天开发遇到的问题,大家都提出自己的看法,最后统一了意见,队员互相 ...

  9. 201521123075 《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. - 了解了多态就是以单一的接口操作多种类型的对象,但是对多态和继承的关系还是有点混乱. - ...

  10. 201521123096《Java程序设计》第二周学习总结

    1.本周学习总结 (1)学会使用码云管理代码: (2)了解数组和字符串的操作: (3)对完全限定类名有一定的认识. 2.书面作业 (1)使用Eclipse关联jdk源代码,并查看String对象的源代 ...