题意:有一棵带点权的树,链修改是把$(x,y)$这条链和与其相邻的节点都加上一个数,查询是问$(x,y)$这条链和与其相邻的节点的权值和

学到了一个新姿势?

考虑树链剖分,在剖重链时每次给当前节点的儿子顺次标号,那么一条重链上所有节点的儿子的标号是连续的,也就对应着题目的限制,再补上漏掉的$lca_{x,y}$和$fa_{lca_{x,y}}$即可

#include<stdio.h>
typedef long long ll;
void swap(int&a,int&b){a^=b^=a^=b;}
int h[100010],nex[200010],to[200010],v[100010],M;
void add(int a,int b){
	M++;
	to[M]=b;
	nex[M]=h[a];
	h[a]=M;
}
int siz[100010],dep[100010],fa[100010],son[100010],n;
void dfs(int x){
	int i,k=0;
	siz[x]=1;
	dep[x]=dep[fa[x]]+1;
	for(i=h[x];i;i=nex[i]){
		if(to[i]!=fa[x]){
			fa[to[i]]=x;
			dfs(to[i]);
			siz[x]+=siz[to[i]];
			if(siz[to[i]]>siz[k])k=to[i];
		}
	}
	son[x]=k;
}
int bl[100010],p[100010],pos[100010],L[100010],R[100010];
void dfs(int x,int chain){
	int i;
	bl[x]=chain;
	L[x]=M+1;
	for(i=h[x];i;i=nex[i]){
		if(to[i]!=fa[x]){
			p[++M]=to[i];
			pos[to[i]]=M;
		}
	}
	R[x]=M;
	if(son[x])dfs(son[x],chain);
	for(i=h[x];i;i=nex[i]){
		if(to[i]!=fa[x]&&to[i]!=son[x])dfs(to[i],to[i]);
	}
}
ll s[400010],d[400010];
void pushup(int x){s[x]=s[x<<1]+s[x<<1|1];}
void build(int l,int r,int x){
	if(l==r){
		s[x]=v[p[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,x<<1);
	build(mid+1,r,x<<1|1);
	pushup(x);
}
void ad(int x,int len,ll v){
	d[x]+=v;
	s[x]+=len*v;
}
void pushdown(int x,int ln,int rn){
	if(d[x]){
		ad(x<<1,ln,d[x]);
		ad(x<<1|1,rn,d[x]);
		d[x]=0;
	}
}
void modify(int L,int R,int v,int l,int r,int x){
	if(L>R)return;
	if(L<=l&&r<=R)return ad(x,r-l+1,v);
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)modify(L,R,v,l,mid,x<<1);
	if(mid<R)modify(L,R,v,mid+1,r,x<<1|1);
	pushup(x);
}
ll query(int L,int R,int l,int r,int x){
	if(L>R)return 0;
	if(L<=l&&r<=R)return s[x];
	int mid=(l+r)>>1;
	ll s=0;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)s+=query(L,R,l,mid,x<<1);
	if(mid<R)s+=query(L,R,mid+1,r,x<<1|1);
	return s;
}
int lca(int x,int y){
	while(bl[x]!=bl[y]){
		if(dep[bl[x]]<dep[bl[y]])swap(x,y);
		x=fa[bl[x]];
	}
	return dep[x]<dep[y]?x:y;
}
void modify(int x,int y,int v){
	int u=lca(x,y);
	while(bl[x]!=bl[u]){
		modify(L[bl[x]],R[x],v,1,n,1);
		x=fa[bl[x]];
	}
	while(bl[y]!=bl[u]){
		modify(L[bl[y]],R[y],v,1,n,1);
		y=fa[bl[y]];
	}
	if(dep[x]>dep[y])swap(x,y);
	modify(L[x],R[y],v,1,n,1);
	modify(pos[x],pos[x],v,1,n,1);
	if(fa[x])modify(pos[fa[x]],pos[fa[x]],v,1,n,1);
}
ll query(int x,int y){
	int u=lca(x,y);
	ll s=0;
	while(bl[x]!=bl[u]){
		s+=query(L[bl[x]],R[x],1,n,1);
		x=fa[bl[x]];
	}
	while(bl[y]!=bl[u]){
		s+=query(L[bl[y]],R[y],1,n,1);
		y=fa[bl[y]];
	}
	if(dep[x]>dep[y])swap(x,y);
	s+=query(L[x],R[y],1,n,1)+query(pos[x],pos[x],1,n,1);
	if(fa[x])s+=query(pos[fa[x]],pos[fa[x]],1,n,1);
	return s;
}
int main(){
	int m,i,x,y,z;
	scanf("%d",&n);
	for(i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	for(i=1;i<=n;i++)scanf("%d",v+i);
	dfs(1);
	M=1;
	p[1]=1;
	pos[1]=1;
	dfs(1,1);
	build(1,n,1);
	scanf("%d",&m);
	while(m--){
		scanf("%d%d%d",&i,&x,&y);
		if(i==1){
			scanf("%d",&z);
			modify(x,y,z);
		}else
			printf("%lld\n",query(x,y));
	}
}

[xsy2123]毛毛虫的更多相关文章

  1. 【HAOI2009】【P1307】毛毛虫

    感觉相比其他树归题简单多了,不过有点绕(也许是我的思路很奇怪一.一)(这是省选题啊,就算作为T1这题也太水了,HA好弱……) 原题: 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一 ...

  2. [haoi2009]毛毛虫 树形dp

    这道题细节处理不少,但要AC不难: 设以i节点为根节点的子树能形成的最大的毛毛虫长度为f[i],则f[i]=max(f[j])+i节点的孩子数: 答案需要f最大和次大的两个子树合并,而且若合并的位置不 ...

  3. [HAOI2009]毛毛虫

    题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...

  4. 【HAOI2009】毛毛虫

    题面 题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入 ...

  5. 【luogu3174】【HAOI2009】毛毛虫

    Description 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大. Input 在文本文件 worm.in 中第一行两个整数 N , M ,分 ...

  6. P3174 [HAOI2009]毛毛虫

    题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...

  7. loj #6570. 毛毛虫计数

    $ \color{#0066ff}{ 题目描述 }$ hsezoi 巨佬 olinr 喜欢 van 毛毛虫,他定义毛毛虫是一棵树,满足树上存在一条树链,使得树上所有点到这条树链的距离最多为 1. 给定 ...

  8. loj6570 毛毛虫计数(生成函数FFT)

    link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...

  9. [洛谷P3174][HAOI2009]毛毛虫

    题目大意:给一棵树,求其中最大的“毛毛虫”,毛毛虫的定义是一条链上分出几条边 题解:把每个点的权值定义为它的度数减一,跑带权直径即可,最后答案加二 卡点:无 C++ Code: #include &l ...

随机推荐

  1. Linux命令--hostname和uname

    hostname命令 hostname命令用于显示和设置系统的主机名称.环境变量HOSTNAME也保存了当前的主机名.在使用hostname命令设置主机名后,系统并不会永久保存新的主机名,重新启动机器 ...

  2. Object的公用方法们

    如图所示,Object一共有10种方法: 下面详细描述: 1.public Object() 方法,默认构造函数方法,当新建一个Object对象的时候,调用这个方法向堆区申请一片内存: 2.priva ...

  3. 最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)(转)

    原文转自 https://blog.csdn.net/leixiaohua1020/article/details/25346147/ 伴随着毕业论文的完成,这两天终于腾出了空闲,又有时间搞搞FFMP ...

  4. python实战===用python识别图片中的中文

    需要安装的模块 PIL pytesseract 需要下载的工具: http://download.csdn.net/download/bo_mask/10196285 因为之前百度云的链接总失效,所以 ...

  5. 【bzoj1072】SCOI2007排列

    状压dp,f[i][j]表示当前取了i,模数余j的状态. 然后向后推,枚举可能的数即可. 注意每个数存在重复,最后要除以相应出现次数的阶乘. #include<bits/stdc++.h> ...

  6. 设计模式之笔记--抽象工厂模式(Abstract Factory)

    抽象工厂模式(Abstract Factory) 定义 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 类图 描述 多个抽象产品 ...

  7. react项目中遇到的一些问题

    推荐使用facebook官方构建工具create-react-app来创建React基础工程.(然而我还是手动构建) (路由)官方旧版本和V4的比较.https://github.com/ReactT ...

  8. HA集群

    //硬件准备: .两个机器,相同系统 .网卡ip为:aming 192.168.11.24 aming1 192.168.11.23 //实验准备: . hostname : aming , amin ...

  9. 关于级联查询,mybatis

    <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-// ...

  10. Context-Aware Network Embedding for Relation Modeling

    Context-Aware Network Embedding for Relation Modeling 论文:http://www.aclweb.org/anthology/P17-1158 创新 ...