[xsy2123]毛毛虫
题意:有一棵带点权的树,链修改是把$(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]毛毛虫的更多相关文章
- 【HAOI2009】【P1307】毛毛虫
感觉相比其他树归题简单多了,不过有点绕(也许是我的思路很奇怪一.一)(这是省选题啊,就算作为T1这题也太水了,HA好弱……) 原题: 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一 ...
- [haoi2009]毛毛虫 树形dp
这道题细节处理不少,但要AC不难: 设以i节点为根节点的子树能形成的最大的毛毛虫长度为f[i],则f[i]=max(f[j])+i节点的孩子数: 答案需要f最大和次大的两个子树合并,而且若合并的位置不 ...
- [HAOI2009]毛毛虫
题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...
- 【HAOI2009】毛毛虫
题面 题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入 ...
- 【luogu3174】【HAOI2009】毛毛虫
Description 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大. Input 在文本文件 worm.in 中第一行两个整数 N , M ,分 ...
- P3174 [HAOI2009]毛毛虫
题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...
- loj #6570. 毛毛虫计数
$ \color{#0066ff}{ 题目描述 }$ hsezoi 巨佬 olinr 喜欢 van 毛毛虫,他定义毛毛虫是一棵树,满足树上存在一条树链,使得树上所有点到这条树链的距离最多为 1. 给定 ...
- loj6570 毛毛虫计数(生成函数FFT)
link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...
- [洛谷P3174][HAOI2009]毛毛虫
题目大意:给一棵树,求其中最大的“毛毛虫”,毛毛虫的定义是一条链上分出几条边 题解:把每个点的权值定义为它的度数减一,跑带权直径即可,最后答案加二 卡点:无 C++ Code: #include &l ...
随机推荐
- 主成分分析(PCA)及其在R里的实现
主成分分析(principal component analysis,PCA)是一种降维技术,把多个变量化为能够反映原始变量大部分信息的少数几个主成分.设X有p个变量,为n*p阶矩阵,即n个样本的p维 ...
- O(1)时间复杂度实现入栈、出栈、获得栈中最小元素、获得栈中最大元素(转)
题目要求:定义栈的数据结构,添加min().max()函数(动态获取当前状态栈中的最小元素.最大元素),要求push().pop().min().max()的时间复杂度都是O(1). 思路解析:根据栈 ...
- 函数导出在kvm_intel.ko,kvm.ko不共享
KVM一共包含了三个内核模块,kvm_intel.ko,kvm_amd.ko,kvm.ko.其中两个重要文件x86.c和vmx.c在编译后分别会生成kvm_intel.ko和kvm.ko两个内核模块, ...
- Redis 3.0 编译安装
Redis 3.0 编译安装 http://www.xuchanggang.cn/archives/991.html
- HTML5API(3)
十一.ajax同源操作 URL说明是否允许通信 同一域名下允许 http://www.a.com/a.js , http://www.a.com/b.js 同一域名下不同文件夹允许 http://ww ...
- docker安装(2016-08-25版本)
. 通过命令对系统的版本进行查看 [root@localhost ~]# uname -a [root@localhost ~]# cat /etc/issue --> 如果是6.5之前的版本 ...
- linux命令(28):scp命令
命令格式:scp [参数] [原路径] [目标路径] 实例1:从远处复制文件到本地目录 scp root@192.168.120.204:/opt/soft/nginx-0.5.38.tar.gz / ...
- How ConcurrentHashMap offers higher concurrency without compromising thread safety
https://www.ibm.com/developerworks/library/j-jtp08223/
- Python 面向对象的三大特性
面向对象的三大特性:继承,封装,多态 什么时候用封装: 同一种功能的时候, 譬如:把一部分数据或方法,封装到同一个类的中 PS:在构造方法中,原始数据中....
- CCF试题:高速公路(Targin)
问题描述 某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路. 现在,大臣们帮国王拟了一个修高速公路的 ...