图很丑。明显的树链剖分,需要的操作只有区间修改和区间查询。不过这里是边权,我们怎么把它转成点权呢?对于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. excel数据导入mysql

    先把excel数据另存成txt文件 Load Data InFile 'D:/1.txt' Into Table `res_type_collect` fields terminated by '@‘ ...

  2. Integer Replacement

    https://leetcode.com/problems/integer-replacement/#/solutions 这题是一道典型的搜索问题,我采用广度搜索,可以直接输出最短路径.这题的tes ...

  3. build配置项中maven常用插件

    <build> <!-- 在浏览器地址栏的项目名称 --> <finalName>${project.artifactId}</finalName> & ...

  4. Spark缓存策略

    当对同一个rdd多次执行action时,如果在磁盘上则每次执行action都会从磁盘将数据加载,如果将其缓存到内存中会提高再次action的读取速度,Spark缓存主要有cache()和persist ...

  5. hdu5701-中位数计数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5701 题目: Problem Description 中位数定义为所有值从小到大排序后排在正中间的那个 ...

  6. teamviewer连接未就绪的解决(Manjaro Linux)

    放假回家,想设置一下teamviewer,结果一直报错"TeamViewer not ready. Please check your connection" 查了一通,发现这个方 ...

  7. The Apache HBase™ Reference Guide

    以下内容由http://hbase.apache.org/book.html#getting_started节选并改编而来. 运行环境:hadoop-1.0.4,hbase-0.94.22,jdk1. ...

  8. ubuntu中如何安装python3.6

    此处使用命令行方式来安装Python3.6: sudo wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz sudo ta ...

  9. 微信公众号_订阅号_爬虫puppeteer

    puppeteer 借助 puppeteer 库实现爬虫,puppeteer 提供了高级 api 接口来操作 chrome 来 npm install puppeteer --save-dev    ...

  10. AngularJS_简介、特性及基本使用_及其工作原理

    转自:angularJS 的工作原理 转自:通过<script>标签引入到 HTML 中,那么此时 Angular 就做为一个普通的 DOM 节点等待浏览器解析 当浏览器解析到这个节点时, ...