[USACO11DEC]牧草种植Grass Planting

图很丑。明显的树链剖分,需要的操作只有区间修改和区间查询。不过这里是边权,我们怎么把它转成点权呢?对于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的更多相关文章
- 洛谷P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)
题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了 代码如下: #include<cstdio> #include<vector> #in ...
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...
- 树链剖分【p3038】[USACO11DEC]牧草种植Grass Planting
表示看不太清. 概括题意 树上维护区间修改与区间和查询. 很明显树剖裸题,切掉,细节处错误T了好久 TAT 代码 #include<cstdio> #include<cstdlib& ...
- 洛谷P3038 牧草种植Grass Planting
思路: 首先,这道题的翻译是有问题的(起码现在是),查询的时候应该是查询某一条路径的权值,而不是某条边(坑死我了). 与平常树链剖分题目不同的是,这道题目维护的是边权,而不是点权,那怎么办呢?好像有点 ...
- USACO Grass Planting
洛谷 P3038 [USACO11DEC]牧草种植Grass Planting 洛谷传送门 JDOJ 2282: USACO 2011 Dec Gold 3.Grass Planting JDOJ传送 ...
随机推荐
- javascript模板引擎template.js使用
到GitHub上下载template.js库.引入到页面 以type="text/html" 这样指定javascript类型的是一种javascript模板渲染方法,在实际项目中 ...
- css_base_note
- UOJ#314. 【NOI2017】整数 其他
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ314.html 题解 如果只加不减,那么瞎势能分析一波可以知道暴力模拟的复杂度是对的. 但是有减法怎么办? ...
- JavaScript中作用域和作用域链的简单理解(变量提升)
通过阅读<JS高级程序设计>这本书,对js中的作用域和作用域链知识有了初步的了解和认识,准备成笔记供大家参考,笔记中字数比较多,但个人认为叙述的挺详细的,所以希望读者耐心看.再者,本人了解 ...
- ruby配合gem使用sass
Ruby环境安装 1.Ruby安装包下载地址:http://rubyinstaller.org/downloads/下载对应系统版本的安装包: 2.双击rubyinstaller-2.2.3-x64. ...
- 2017 CCPC Qinhuangdao Site
A. Balloon Robot 假设机器人$0$时刻位于$0$号位置,那么每个气球所需的时间为$(s_a-b)\bmod m$. 将所有气球按这个时间排序,枚举每个气球的时间作为偏移量,得出最优解即 ...
- 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
A. Odd Palindrome 所有回文子串长度都是奇数等价于不存在长度为$2$的偶回文子串,即相邻两个字符都不同. #include<cstdio> #include<cstr ...
- XVIII Open Cup named after E.V. Pankratiev. Eastern Grand Prix
A. Artifacts 建立语法分析树,首先根据上下界判断是否有解,然后将所有数按下界填充,线段树判断是否存在和超过$K$的子区间. B. Brackets and Dots 最优解中一定包含一对中 ...
- Understanding HBase and BigTable
Hbase is a distributed data storage systems. A Bigtable is spare , distributed , persistent multidim ...
- STL--set_difference
set_difference(),作用是求两个集合的差.即求A-B(属于A但不属于B的元素) set_difference()算法计算两个集合[start1, end1)和[start2, end2) ...