图很丑。明显的树链剖分,需要的操作只有区间修改和区间查询。不过这里是边权,我们怎么把它转成点权呢?对于E(u,v),我们选其深度大的节点,把边权扔给它。因为这是树,所以每个点只有一个父亲,所以每个边权都可以唯一地、不重复地转移到点上去(除了根节点)。但是做区间操作时就要注意一下,区间两边端点的LCA的权值是不可以用的。


  这么简单的模板题就直接放代码了:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1000001
#define maxm 1000001
using namespace std; struct edge{
int to,next;
edge(){}
edge(const int &_to,const int &_next){ to=_to,next=_next; }
}e[maxn<<];
int head[maxn],k; struct node{
int l,r,c,f;
}t[maxn<<]; int size[maxn],son[maxn],fa[maxn],dep[maxn];
int dfn[maxn],id[maxn],top[maxn],tot;
int n,m; inline int read(){
register int x(); register char c(getchar());
while(c<''||''<c) c=getchar();
while(''<=c&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x;
} inline void add(const int &u,const int &v){
e[k]=edge(v,head[u]);
head[u]=k++;
} void dfs_getson(int u){
size[u]=;
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]) continue;
fa[v]=u,dep[v]=dep[u]+;
dfs_getson(v);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
} void dfs_rewrite(int u,int tp){
top[u]=tp,dfn[u]=++tot,id[tot]=u;
if(son[u]) dfs_rewrite(son[u],tp);
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v!=son[u]&&v!=fa[u]) dfs_rewrite(v,v);
}
} void build(int d,int l,int r){
t[d].l=l,t[d].r=r;
if(l==r) return;
int mid=(l+r)>>;
build(d<<,l,mid),build(d<<|,mid+,r);
} inline void down(const int &d){
t[d<<].c+=t[d].f*(t[d<<].r-t[d<<].l+),t[d<<].f+=t[d].f;
t[d<<|].c+=t[d].f*(t[d<<|].r-t[d<<|].l+),t[d<<|].f+=t[d].f;
t[d].f=;
} void change(int d,const int &l,const int &r){
if(l<=t[d].l&&t[d].r<=r){
t[d].c+=t[d].r-t[d].l+,t[d].f++;
return;
}
if(t[d].f) down(d);
int mid=(t[d].l+t[d].r)>>;
if(l<=mid) change(d<<,l,r);
if(r>mid) change(d<<|,l,r);
t[d].c=t[d<<].c+t[d<<|].c;
} inline void change_path(){
int u=read(),v=read();
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]) swap(u,v);
change(,dfn[top[v]],dfn[v]);
v=fa[top[v]];
}
if(dep[u]>dep[v]) swap(u,v);
change(,dfn[u]+,dfn[v]);//加1是因为不能用LCA的权值
} int getsum(int d,const int &l,const int &r){
if(l<=t[d].l&&t[d].r<=r) return t[d].c;
if(t[d].f) down(d);
int mid=(t[d].l+t[d].r)>>,ans=;
if(l<=mid) ans+=getsum(d<<,l,r);
if(r>mid) ans+=getsum(d<<|,l,r);
return ans;
} inline void getsum_path(){
int u=read(),v=read(),ans=;
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]) swap(u,v);
ans+=getsum(,dfn[top[v]],dfn[v]);
v=fa[top[v]];
}
if(dep[u]>dep[v]) swap(u,v);
ans+=getsum(,dfn[u]+,dfn[v]);//加1是因为不能用LCA的权值
printf("%d\n",ans);
} int main(){
memset(head,-,sizeof head);
n=read(),m=read();
int u,v;
for(register int i=;i<n;i++){
u=read(),v=read();
add(u,v),add(v,u);
}
dfs_getson();
dfs_rewrite(,);
build(,,tot); char op;
for(register int i=;i<=m;i++){
scanf("%s",&op);
if(op=='P') change_path();
else getsum_path();
}
return ;
}

[USACO11DEC]牧草种植Grass Planting的更多相关文章

  1. 洛谷P3038 [USACO11DEC]牧草种植Grass Planting

    题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...

  2. AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038

    题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...

  3. 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting

    题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...

  4. P3038 [USACO11DEC]牧草种植Grass Planting

    题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...

  5. 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)

    题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了 代码如下: #include<cstdio> #include<vector> #in ...

  6. 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】

    模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...

  7. 树链剖分【p3038】[USACO11DEC]牧草种植Grass Planting

    表示看不太清. 概括题意 树上维护区间修改与区间和查询. 很明显树剖裸题,切掉,细节处错误T了好久 TAT 代码 #include<cstdio> #include<cstdlib& ...

  8. 洛谷P3038 牧草种植Grass Planting

    思路: 首先,这道题的翻译是有问题的(起码现在是),查询的时候应该是查询某一条路径的权值,而不是某条边(坑死我了). 与平常树链剖分题目不同的是,这道题目维护的是边权,而不是点权,那怎么办呢?好像有点 ...

  9. USACO Grass Planting

    洛谷 P3038 [USACO11DEC]牧草种植Grass Planting 洛谷传送门 JDOJ 2282: USACO 2011 Dec Gold 3.Grass Planting JDOJ传送 ...

随机推荐

  1. [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入

    https://www.cnblogs.com/masonlu/p/10105135.html

  2. 2.基于梯度的攻击——FGSM

    FGSM原论文地址:https://arxiv.org/abs/1412.6572 1.FGSM的原理 FGSM的全称是Fast Gradient Sign Method(快速梯度下降法),在白盒环境 ...

  3. 配置ubuntu的超管账号密码

    1 在搭建ubuntu 之后 只有自己的账号 2 root 用户是没有配置好的 需要重新配置 3 passwd root 4 输入新密码即可

  4. 网页布局之grid

    学习网格布局时,你可能会在网络上看到很多文章,内容不同,属性不同,真是让人摸不着头脑,到底哪个才是正确的?看了本篇文章,我想你会豁然开朗.比如,一会儿用grid-rows,一会儿用grid-defin ...

  5. http连接基础类,负责底层的http通信

    /// <summary> /// http连接基础类,负责底层的http通信 /// </summary> public class HttpService { public ...

  6. 2019-2-14SQLserver中function函数和存储过程、触发器、CURSOR

    Sqlserver 自定义函数 Function使用介绍 前言:         在SQL server中不仅可以可以使用系统自带的函数(时间函数.聚合函数.字符串函数等等),还可以根据需要自定义函数 ...

  7. 2017-10-22—光电二极管

    光通信基本每天都会接触光电二极管,光模块说简单点就是电光转换和光电转换. 光传输模块在整体产品架构上则包括光学次模块(Optical Subassembly;OSA)及电子次模块(Electrical ...

  8. Android的Launcher启动流程 “Launcher部分启动流程”

    研究代码从:AndroidManifest.xml.自定义的Application.java开始. Android系统启动时,系统需要一个Home应用程序来负责将这些应用程序展示出来:也就是该应用的目 ...

  9. ElasticSearch 6.4.3 启动报错: [Cannot assign requested address: bind]

    今天在本地搭建一个测试用的最新版ElasticSearch6.4.3 的环境时,遇到一个报: [Cannot assign requested address: bind]的错误. 错误日志内容如下: ...

  10. maven入门概念及使用

    Maven 一.Maven概念 1.maven是什么:Maven 是一个项目管理工具.它负责管理项目开发过程中的几乎所有的东西. 版本.构建.输出物管理.依赖关系.文档和构建结果.项目关系.移植性管理 ...