思路:

首先,这道题的翻译是有问题的(起码现在是),查询的时候应该是查询某一条路径的权值,而不是某条边(坑死我了)。

与平常树链剖分题目不同的是,这道题目维护的是边权,而不是点权,那怎么办呢?好像有点棘手诶,这是一种非常经典的题型,我们可以发现,一个点最多只有一个父亲!!!那,我们显然就可以用这个点的点权去代替它与它父亲之间的边权!!!然后这道题不就成了树链剖分水题了嘛?刚开始边权都是\(0\),那我们就根据题目给的边建边权为\(0\)的边。

\(nonono\),还有一个坑点就是在路径查询和修改的时候,两点的\(LCA\)的点权是不能算在其中的,因为它的点权是\(LCA\)与\(LCA\)父亲之间边的边权,注意这几个问题,那这题就真的是水题了!

自己整理的题解

具体实现看代码:

#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 100007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
int n,m,head[maxn],d[maxn],son[maxn],siz[maxn],id[maxn],w[maxn];
int num,cnt,sum[maxn<<2],lazy[maxn<<2],top[maxn],fa[maxn],a[maxn];
char s[3];
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int v,w,nxt;
}e[maxn<<1];
inline void ct(int u, int v, int w) {
e[++num].v=v;
e[num].w=w;
e[num].nxt=head[u];
head[u]=num;
}
inline void pushup(int rt) {
sum[rt]=sum[ls]+sum[rs];
}
void build(int rt, int l, int r) {
if(l==r) {
sum[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
inline void pushdown(int rt, int len) {
if(lazy[rt]) {
sum[ls]+=(len-(len>>1))*lazy[rt];
sum[rs]+=(len>>1)*lazy[rt];
lazy[ls]+=lazy[rt],lazy[rs]+=lazy[rt];
lazy[rt]=0;
}
}
void modify(int rt, int l, int r, int L, int R, int val) {
if(L>r||R<l) return;
if(L<=l&&r<=R) {
sum[rt]+=(r-l+1)*val;
lazy[rt]+=val;
return;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
pushup(rt);
}
int csum(int rt, int l, int r, int L, int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return sum[rt];
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
return csum(ls,l,mid,L,R)+csum(rs,mid+1,r,L,R);
}
void dfs1(int u) {
siz[u]=1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa[u]) {
d[v]=d[u]+1;
fa[v]=u;
w[u]=e[i].w;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u, int t) {
id[u]=++cnt;
top[u]=t;
a[cnt]=w[u];
if(son[u]) dfs2(son[u],t);
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void cal(int x, int y) {
int fx=top[x],fy=top[y];
while(fx!=fy) {
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
modify(1,1,cnt,id[fx],id[x],1);
x=fa[fx],fx=top[x];
}
if(id[x]>id[y]) swap(x,y);
modify(1,1,cnt,id[x]+1,id[y],1);
}
int query(int x, int y) {
int fx=top[x],fy=top[y],ans=0;
while(fx!=fy) {
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
ans+=csum(1,1,cnt,id[fx],id[x]);
x=fa[fx],fx=top[x];
}
if(id[x]>id[y]) swap(x,y);
ans+=csum(1,1,cnt,id[x]+1,id[y]);
return ans;
}
int main() {
n=qread(),m=qread();
for(int i=1,u,v;i<n;++i) {
u=qread(),v=qread();
ct(u,v,0);ct(v,u,0);
}
dfs1(1);dfs2(1,1);build(1,1,n);
for(int i=1,u,v;i<=m;++i) {
scanf("%s",s);
u=qread(),v=qread();
if(s[0]=='P') cal(u,v);
else printf("%d\n",query(u,v));
}
return 0;
}

洛谷P3038 牧草种植Grass Planting的更多相关文章

  1. 洛谷P3038 牧草种植 [树链剖分]

    题目传送门 牧草种植 题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirec ...

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

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

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

    题目描述 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. P3038 [USACO11DEC]牧草种植Grass Planting

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

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

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

  8. [USACO11DEC]牧草种植Grass Planting

    图很丑.明显的树链剖分,需要的操作只有区间修改和区间查询.不过这里是边权,我们怎么把它转成点权呢?对于E(u,v),我们选其深度大的节点,把边权扔给它.因为这是树,所以每个点只有一个父亲,所以每个边权 ...

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

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

随机推荐

  1. 绘图工具--turtle模块

    turtle模块主要使用两个类,一个是TurtleScreen类,表示画布(窗口),用来展示画的位置:一个是Turtle类,用来充当画笔,用来画. 两个类的方法也以同名的函数的形式存在,所以可以以面向 ...

  2. 【遍历二叉树】04二叉树的层次遍历【Binary Tree Level Order Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的层次遍历的 ...

  3. ffmpeg编码h264只包含I帧P帧的方法

    ffmpeg使用avcodc_encode_video编码,默认产生的h264包含B帧,在安防行业很多地方是不需要用到B帧的. 1.基础知识充电 这就涉及到h264的各种profile格式了,参考 h ...

  4. 基于FTP服务、JAVA实现文件同步操作

    package lixj.ftp; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStre ...

  5. L1-039 古风排版(20 分)

    中国的古人写文字,是从右向左竖向排版的.本题就请你编写程序,把一段文字按古风排版. 输入格式: 输入在第一行给出一个正整数N(<100),是每一列的字符数.第二行给出一个长度不超过1000的非空 ...

  6. 洛谷【P1236】算24点

    我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:https://www.luogu.org/problemnew/show/P ...

  7. debian服务查询

    1.查询 用root身份执行service --status-all查看所有服务的状态 "+" started "-" stopped "?" ...

  8. 【转】 Pro Android学习笔记(七六):服务(1):local和remote

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...

  9. error: converting to execution character set: Invalid or incomplete multibyte or wide character

    交叉编译.c文件,遇到如下问题 arm-linux-gcc -o show_lines show_lines.c -lfreetype -lm show_lines.c:199:19: error: ...

  10. SpringMVC执行流程简介

    1.用户向服务器发送请求,请求被SpringMVC的前端控制器DispatcherServlet截获. 2.DispatcherServlet对请求的URL(统一资源定位符)进行解析,得到URI(请求 ...