[USACO11DEC] Grass Planting (树链剖分)
题目描述
Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional roads, such that there is exactly one path between any two pastures. Bessie, a cow who loves her grazing time, often complains about how there is no grass on the roads between pastures. Farmer John loves Bessie very much, and today he is finally going to plant grass on the roads. He will do so using a procedure consisting of M steps (1 <= M <= 100,000).
At each step one of two things will happen:
FJ will choose two pastures, and plant a patch of grass along each road in between the two pastures, or,
Bessie will ask about how many patches of grass on a particular road, and Farmer John must answer her question.
Farmer John is a very poor counter -- help him answer Bessie's questions!
给出一棵n个节点的树,有m个操作,操作为将一条路径上的边权加一或询问某条边的权值。
输入输出格式
输入格式:
Line 1: Two space-separated integers N and M
Lines 2..N: Two space-separated integers describing the endpoints of a road.
Lines N+1..N+M: Line i+1 describes step i. The first character of the line is either P or Q, which describes whether or not FJ is planting grass or simply querying. This is followed by two space-separated integers A_i and B_i (1 <= A_i, B_i <= N) which describe FJ's action or query.
输出格式:
- Lines 1..???: Each line has the answer to a query, appearing in the same order as the queries appear in the input.
输入输出样例
输入样例#1:
4 6
1 4
2 4
3 4
P 2 3
P 1 3
Q 3 4
P 1 4
Q 2 4
Q 1 4
输出样例#1:
2
1
2
Solution
树剖板子题,关键是注意统计的是边的权值,不是点的权值。
只需要在每次修改或者查询的时候将其 LCA 的 id +1,即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=100008;
int n,m;
struct sj{
int to;
int next;
}a[maxn*2];
int size,head[maxn];
void add(int x,int y)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
}
int dep[maxn],fa[maxn];
int top[maxn],son[maxn];
int siz[maxn];
void dfs(int x)
{
siz[x]=1;
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(!siz[tt])
{
dep[tt]=dep[x]+1;
fa[tt]=x;
dfs(tt);
siz[x]+=siz[tt];
if(siz[tt]>siz[son[x]])
son[x]=tt;
}
}
}
int id[maxn],num;
void dfs1(int x,int y)
{
top[x]=y;
id[x]=++num;
if(son[x])
dfs1(son[x],y);
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(!top[tt])
if(tt!=son[x])
dfs1(tt,tt);
}
}
int sgm[maxn*4],lazy[maxn*4];
void push_down(int node,int l,int r)
{
int kk=lazy[node],mid=(l+r)/2;
lazy[node*2]+=kk;
lazy[node*2+1]+=kk;
sgm[node*2]+=(mid-l+1)*kk;
sgm[node*2+1]+=(r-mid)*kk;
lazy[node]=0;
}
void change(int node,int left,int right,int l,int r)
{
int v=1;
if(left>r||right<l)
return;
if(left>=l&&right<=r)
{
sgm[node]+=v*(right-left+1);
lazy[node]+=v;
return;
}
push_down(node,left,right);
int dist=(right+left)/2;
change(node*2,left,dist,l,r);
change(node*2+1,dist+1,right,l,r);
sgm[node]=sgm[node*2]+sgm[node*2+1];
return;
}
int query(int node,int left,int right,int l,int r)
{
if(l>right||r<left)
return 0;
if(right<=r&&left>=l)
return sgm[node];
push_down(node,left,right);
int dist=(left+right)/2;
return query(node*2,left,dist,l,r)+query(node*2+1,dist+1,right,l,r);
}
void kuai(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
change(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
change(1,1,n,id[x]+1,id[y]);
return;
}
int check(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans+=query(1,1,n,id[x]+1,id[y]);
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dep[1]=1;
dfs(1);
dfs1(1,1);
while(m--)
{
char ch;
int x,y;
cin>>ch; scanf("%d%d",&x,&y);
if(ch=='Q')
cout<<check(x,y)<<endl;
else
kuai(x,y);
}
}
[USACO11DEC] Grass Planting (树链剖分)的更多相关文章
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)
题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了 代码如下: #include<cstdio> #include<vector> #in ...
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...
- spoj - Grass Planting(树链剖分模板题)
Grass Planting 题意 给出一棵树,树有边权.每次给出节点 (u, v) ,有两种操作:1. 把 u 到 v 路径上所有边的权值加 1.2. 查询 u 到 v 的权值之和. 分析 如果这些 ...
- 树链剖分好(du)题(liu)选做
1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
- 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...
随机推荐
- MySQL 外键 表的查询
自增补充 这是查看怎么创建的表, \G示旋转90度显示表的内容 表的自增的关键是** AUTO_INCREMENT=3**,在表中添加数据后,这个会自动改变,通过alert可以改变这个默认值 mysq ...
- CPP-STL:vector中的size和capacity
在vector中与size()和capacity() 相对应的有两个函数: resize(size_type)和reserve(size_type). Size指目前容器中实际有多少元素,对应的res ...
- CPP-基础:new int[]跟int()的区别
1. new int[] 是创建一个int型数组,数组大小是在[]中指定,例如: int * p = new int[10]; //p执行一个长度为10的int数组.2. new int()是创建一个 ...
- 利用Python的pyHook包来进行键盘监听
最近在实习的时候发现一件很蛋疼的事情,那就是我们组的项目因为有后台进程,所有每次运行完以后后台进程都必须要自己手动关闭,每次编译之前忘记关就会有一大堆编译错误,我就想直接弄个可以快捷键直接关闭算了 ...
- 主题模型LDA及在推荐系统中的应用
1 关于主题模型 使用LDA做推荐已经有一段时间了,LDA的推导过程反复看过很多遍,今天有点理顺的感觉,就先写一版. 隐含狄利克雷分布简称LDA(latent dirichlet allocation ...
- C#基础-数组
数组定义 定义数组并赋值 int[] scores = { 45, 56, 78, 98, 100 }; //在定义数组时赋值 for(int i = 0; i < scores.Length; ...
- python入门:输出1-100之内的所有奇数和偶数
#!/usr/bin/env python # -*- coding:utf-8 -*- #输出1-100之内的所有奇数和偶数 """ 给start赋值等于1,while ...
- python-for循环与while循环
while 循环 格式: while 条件 为 True: 代码块 while True: rayn_age = 18 age = input('请输入你的年龄:') age = int(age) i ...
- day12-迭代器
迭代器的概念 内部含有_next_和_iter_方法的就是迭代器. 可以被for循环的都是可迭代的,只有是可迭代对象,才能用for循环. 可迭代的内部都有_iter_方法——可迭代协议. 只要是迭代器 ...
- Leetcode(204) Count Primes
题目 Description: Count the number of prime numbers less than a non-negative number, n. Credits: Speci ...