题意

一棵树上有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. char数组

    *****************************************************************char 类型的数组(c语言中是没有字符串的)char name[20 ...

  2. SQLServer 2005 和自增长主键identity说再见——NEWSEQUENTIALID()

    ``code 在SQLServer2005环境下,表的主键应该怎样设计. 目前主要用到的主键方案共三种 自动增长主键 手动增长主键 UNIQUEIDENTIFIER主键 1.先说自动增长主键,它的优点 ...

  3. OpenCL双边滤波实现美颜功能

    OpenCL是一个并行异构计算的框架,包括intel,AMD,英伟达等等许多厂家都有对它的支持,不过英伟达只到1.2版本,主要发展自己的CUDA去了.虽然没有用过CUDA,但个人感觉CUDA比Open ...

  4. MongoDB.Driver 2.4以上版本 在.NET中的基本操作

    MongoDB.Driver是操作mongo数据库的驱动,最近2.0以下版本已经从GitHub和Nuget中移除了,也就是说.NET Framework4.0不再能从官方获取到MongoDB的驱动了, ...

  5. linux杀毒软件clamav安装与使用

    #clamav安装与使用 ###第一步:Clamav下载http://www.clamav.net/downloads wget http://www.clamav.net/downloads/pro ...

  6. 使用群晖NAS:配置Git server

    1.首先在群晖的DSM的控制面板中创建一个用户例如是Git_test(我给了管理员权限) 2.在套件中心安装 Git server 3.打开Git server 勾选用户 Git_test 4.在控制 ...

  7. mysql和SqlServer 中取得汉字字段的各汉字首字母

    mysql 中取得汉字字段的各汉字首字母 这个转载于http://blog.csdn.net/lky5387/article/details/11973721 DELIMITER ;;CREATE  ...

  8. eureka-3-常用注解

    @EnableDiscoveryClient @EnableEurekaClient 上面两个注解都是用在应用的启动类上面,声明这是一个Eureka Client ,现在说明两个注解的区别. spri ...

  9. C++/C extern关键字详解 EntryPointNotFoundException处理

    最近在弄C#帮公司做一个图像识别的功能,用到了第三方的dll,在调用dll过程中就出现了一个问题.EntryPointNotFoundException异常.遇到这种异常,很大可能就是在生成dll时函 ...

  10. Python基础学习----字符串的常用方法

    # Python字符串 # 大多数的语言定义字符串是双引号,Python既可以双引号,也可以单引号.但使用也有区别 # 单双引号的使用 My_name="bai-boy" Demo ...