题意

一棵树上有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本身

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

分析

树剖模板题。时间复杂度\(O(n + q\log n)\)

代码

BZOJ因为我那个major不让我过编译……只好在洛谷上交了。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll; co int N=3e4+1;
std::vector<int> g[N];
int n,w[N],fa[N],dep[N],siz[N],son[N],top[N],pos[N],dfn,ref[N];
namespace T{
int max[N*4],sum[N*4];
#define lson x<<1
#define rson x<<1|1
void pushup(int x){
max[x]=std::max(max[lson],max[rson]);
sum[x]=sum[lson]+sum[rson];
}
void build(int x,int l,int r){
if(l==r){
max[x]=sum[x]=w[ref[l]];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid),build(rson,mid+1,r);
pushup(x);
}
void modify(int x,int l,int r,int p,int v){
if(l==r){
max[x]=sum[x]=v;
return;
}
int mid=(l+r)>>1;
if(p<=mid) modify(lson,l,mid,p,v);
else modify(rson,mid+1,r,p,v);
pushup(x);
}
int major(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return max[x];
int mid=(l+r)>>1;
if(qr<=mid) return major(lson,l,mid,ql,qr);
if(ql>mid) return major(rson,mid+1,r,ql,qr);
return std::max(major(lson,l,mid,ql,qr),major(rson,mid+1,r,ql,qr));
}
int summation(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return sum[x];
int mid=(l+r)>>1;
if(qr<=mid) return summation(lson,l,mid,ql,qr);
if(ql>mid) return summation(rson,mid+1,r,ql,qr);
return summation(lson,l,mid,ql,qr)+summation(rson,mid+1,r,ql,qr);
}
}
void dfs1(int x,int fa){
::fa[x]=fa,dep[x]=dep[fa]+1,siz[x]=1;
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(y==fa) continue;
dfs1(y,x),siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int top){
::top[x]=top,pos[x]=++dfn,ref[dfn]=x;
if(!son[x]) return;
dfs2(son[x],top);
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
void modify(int x,int v){
T::modify(1,1,n,pos[x],v);
}
int major(int x,int y){
int ans=-30000;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
ans=std::max(ans,T::major(1,1,n,pos[top[x]],pos[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y]) std::swap(x,y);
ans=std::max(ans,T::major(1,1,n,pos[y],pos[x]));
return ans;
}
int summation(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
ans+=T::summation(1,1,n,pos[top[x]],pos[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y]) std::swap(x,y);
ans+=T::summation(1,1,n,pos[y],pos[x]);
return ans;
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n);
for(int i=1;i<n;++i){
int x=read<int>(),y=read<int>();
g[x].push_back(y),g[y].push_back(x);
}
for(int i=1;i<=n;++i)
read(w[i]);
dfs1(1,0),dfs2(1,1);
T::build(1,1,n);
int q=read<int>();
char cmd[10];
while(q--){
scanf("%s",cmd);
if(cmd[1]=='H'){
int x=read<int>(),v=read<int>();
modify(x,v);
}
else if(cmd[1]=='M'){
int x=read<int>(),y=read<int>();
printf("%d\n",major(x,y));
}
else{
int x=read<int>(),y=read<int>();
printf("%d\n",summation(x,y));
}
}
return 0;
}

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

  1. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  2. bzoj1036 [ZJOI2008]树的统计Count

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

  3. BZOJ 1036: [ZJOI2008]树的统计Count

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

  4. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

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

  5. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  6. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  7. 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12266  Solved: 4945[Submit ...

  8. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  9. 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 7496  Solved: 3078[Submit] ...

随机推荐

  1. 可以,得驾证了\(^o^)/

    说实在话,我自认为我不太适合开车. 首先我有点晕车,在车上坐久了就头晕脑胀. 心里素质也不行,凡是遇到什么事了,就慌慌张张,手忙脚乱. 然后就是练车一点都不稳,每次练车都会有新问题出现. 先说一下我科 ...

  2. 如何成为 Python 高手

    这篇文章主要是对我收集的一些文章的摘要.因为已经有很多比我有才华的人写出了大量关于如何成为优秀Python程序员的好文章. 我的总结主要集中在四个基本题目上:函数式编程,性能,测试,编码规范.如果一个 ...

  3. Hibernate中"二级缓存"配置

    实体类 : package cn.happy.entity; public class Emp { private Integer empNo; private String empName; pub ...

  4. jQuery-瀑布流的取巧做法分享

      分析:瀑布流,做法有2种 (1)绝对定位方案:每个单元格设置为绝对定位,通过计算,分别设置 top , left 即可实现 (2)浮动方案:弄N列布局(浮动),然后图片数据,按顺序依次插入,如N为 ...

  5. 使用samba初始化开发环境

    一.系统环境 [root@host-172-20-3-66 samba]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 搞 ...

  6. CUDA库函数使用笔记与案例(一)

    项目合作中需要整合对方公司提供的CUDA代码,因此需要详细学习代码中涉及的cuda函数. CUDA Tool Kit 8.0较完整的官方说明文档: http://docs.nvidia.com/cud ...

  7. EFM32 ARM+ KEIl program

    1Hardware connection When using the EFM32 starter kit to make a JLINK burn, you must connect the con ...

  8. pcm ulaw alaw转换

    static byte ALawCompressTable[] = { 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5 ...

  9. GPU编程自学4 —— CUDA核函数运行参数

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  10. tensorflow_gpu-1.2.1-cp35-cp35m-win_amd64.whl文件怎么安装?

    当你从迅雷下载之后,怎么样来安装上面的文件呢? 这也是一个问题,对于新手来说,是不知道的.其实比较简单,如下: 用命令:pip  install tensorflow_gpu-1.2.1-cp35-c ...