树上差分 (瞎bb) [树上差分][LCA]
做noip2015的运输计划写了好久好久写不出来 QwQ
于是先来瞎bb一下树上差分 混积分
树上差分有2个常用的功能:
(1)记录从点i到i的父亲这条路径走过几次
(2)将每条路径(s,t)上的每个点权值增加1,求各点权值
首先我们建立权值数组sum[]
对于(1),对于每一条路径(s,t),操作: sum[s]++; sum[t]++; sum[lca(s,t)]-=2;
再利用dfs将子节点的sum值加入到父亲节点中即可
sum[i]的数值就表示从点i到i的父亲这条路径走过几次
对于(2),对于每一条路径(s,t),操作:sum[s]++; sum[t]++; sum[lca(s,t)]--; sum[father[lca(s,t]]--;
再利用dfs将子节点的sum值加入到父亲节点中即可
sum[i]表示每一点的权值
贴上(1)的代码
ps1:利用tarjan算法求出lca(s,t)
ps2:无向边变单向边增加效率 真的吗→_→
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std; //来点有理有据的底层优化吧!
inline int read(){
int re=;
char ch;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=(re<<)+(re<<)+ch-'';
return flag?-re:re;
} struct edge{
int to,next;
edge(int to=,int next=):
to(to),next(next){}
}; struct ask{
int from,to,lca;
ask(int from=,int to=,int lca=):
from(from),to(to),lca(lca){}
}; typedef pair<int,int> PII; const int maxn=; vector<edge> edges;
vector<edge> ques;
vector<edge> tree;
vector<ask> qu;
int head[maxn],had[maxn];
int tmp_head[maxn];
int F[maxn],son[maxn];
int sum[maxn];
int n,q,root;
int cnt;
int par[maxn];
bool vis[maxn]; inline void add_edge(int from,int to){
edges.push_back(edge(to,head[from]));
head[from]=++cnt;
edges.push_back(edge(from,head[to]));
head[to]=++cnt;
} inline void add_ques(int from,int to){
ques.push_back(edge(to,had[from]));
had[from]=++cnt;
ques.push_back(edge(from,had[to]));
had[to]=++cnt;
} //把双向边转为单向边
//ps 一般不用对吧
inline void add_branch(int from,int to){
tree.push_back(edge(to,tmp_head[from]));
tmp_head[from]=++cnt;
} void make_tree(int x,int fa){
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa){
add_branch(x,edges[ee].to);
make_tree(edges[ee].to,x);
}
} void init(){
n=read(),q=read(),root=read();
cnt=;
edges.push_back(edge(,));
for(int i=;i<n;i++){
int from=read(),to=read();
add_edge(from,to);
}
cnt=;
ques.push_back(edge(,));
for(int i=;i<q;i++){
int from=read(),to=read();
qu.push_back(ask(from,to,));
add_ques(from,to);
}
cnt=;
tree.push_back(edge(,));
make_tree(root,);
swap(head,tmp_head);
} int find(int x){
return par[x]==x?x:par[x]=find(par[x]);
} //求lca
void tarjan(int x){
for(int ee=head[x];ee;ee=tree[ee].next){
tarjan(tree[ee].to);
par[tree[ee].to]=x;
vis[tree[ee].to]=;
}
for(int ee=had[x];ee;ee=ques[ee].next)
if(vis[ques[ee].to])
qu[(ee-)>>].lca=find(ques[ee].to);
} void dfs_sum(int x){
for(int ee=head[x];ee;ee=tree[ee].next){
dfs_sum(tree[ee].to);
sum[x]+=sum[tree[ee].to];
}
} void solve(){
for(int i=;i<=n;i++) par[i]=i;
tarjan(root); for(int i=;i<q;i++){
ask qq=qu[i];
sum[qq.from]++;
sum[qq.to]++;
sum[qq.lca]-=;
}
dfs_sum(root); for(int i=;i<=n;i++)
printf("%d ",sum[i]);
} int main(){
//freopen("temp.in","r",stdin);
init();
solve();
return ;
}
树上差分 (瞎bb) [树上差分][LCA]的更多相关文章
- 差分数组 and 树上差分
差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易 ...
- 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径
51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...
- SPOJ 10628 COT - Count on a tree(在树上建立主席树)(LCA)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
- 置换群(本蒟蒻瞎BB的)(未完)
置换群(本蒟蒻瞎BB的)(未完) 群的定义 给定一个集合\(G=\{a, b, c...\}\)和集合\(G\)上的二元运算*,并满足: 封闭性:\(\forall a, b \in G, \exis ...
- 洛谷P2664 树上游戏 【点分治 + 差分】
题目 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 现在他想让你求出所有的sum[i] 输入格式 第一行为一个整数n,表示树节点的数量 ...
- Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)
题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...
- loj 1257 (求树上每一个点到树上另一个点的最长距离)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1257 思路:首先需要用到一个知识点就是树上任一点到树上最长直径的某一个端点的距离最远, ...
- hdu 2196(求树上每个节点到树上其他节点的最远距离)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196 思路:首先任意一次dfs求出树上最长直径的一个端点End,然后以该端点为起点再次dfs求出另一个 ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- Dom元素的Property和Attribute
Attribute就是DOM节点自带的属性,例如html中常用的id.class.title.align等: 而Property是这个DOM元素作为对象,其附加的内容,例如childNodes.fir ...
- python网络爬虫之LXML与HTMLParser
Python lxml包用于解析html和XML文件,个人觉得比beautifulsoup要更灵活些 Lxml中的路径表达式如下: 在下面的表格中,我们已列出了一些路径表达式以及表达式的结果: 路径表 ...
- 使用CSS3动画实现绚丽的照片墙效果
临近毕业了,一大波毕业照又要来袭了!如何使用CSS3属性制作出自己的网页版照片墙呢? 闲话少说,先来看看效果图 效果要求: 1,照片要求有一定的白色边框. 2,照片都要有一定的倾斜角度. 3,鼠标移动 ...
- 【Python3之面向对象进阶】
一.isinstance和issubclass 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj=Foo() p ...
- Kafka官方文档翻译——简介
简介 Kafka擅长于做什么? 它被用于两大类应用: 在应用间构建实时的数据流通道 构建传输或处理数据流的实时流式应用 几个概念: Kafka以集群模式运行在1或多台服务器上 Kafka以topics ...
- Qt开发陷阱一QSTACKWIDGET
原始日期:2015-10-14 00:55 1.使用QStackWidget控件的setCurrentIndex方法时,要注意参数0对应着ui上StackWidget的page1,而不是page0,没 ...
- sqlserver 复制表结构(可以含有数据 或 只要表结构)
sqlserver 复制表结构(可以含有数据 或 只要表结构) SELECT * INTO bb FROM aa(NOLOCK) WHERE 1=0
- C#实现手机发送验证码
之前不怎么了解这个,一直以为做起来很复杂. 直到前两天公司要求要做这个功能. 做了之后才发现 这不过就是一个POST请求就能实现的东西.现在给大家分享一下,有不足之处还请多多指教. 废话不多说 直接上 ...
- 我的学习之路_第二十一章_JDBC连接池
JDBC连接池和DButils [DBCP连接池工具类] 使用读取配置文件的方式 DBCP中有一个工厂类 BasicDataSourceFactory 工厂类中有一个静态方法 返回值为: DataSo ...
- 【LeetCode】258. Add Digits
题目: Given a non-negative integer num, repeatedly add all its digits until the result has only one di ...