树上差分 (瞎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 ...
随机推荐
- Xamarin开发笔记—百度在线语音合成
语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的.或外部输入的文字信息转变为可以听得懂的.流利的口语输出的技术. 技术选型:语音合成初步选择有两个,一是讯飞.二是百度. 因为使用的是X ...
- java基础(一章)
java基础(一章) 1. java是一种面向对象的高级编程语言. 2. java包括: javase(java基础) ...
- cpp(第十章)
1. const class & func(const class &) const { do something.. } 第一个const返回后的类不允许被赋值,第二个const不允 ...
- 你是否也在学习ES6 Promise时遇到过这个问题?
背景 周末闲来无事,随便翻看了一下阮一峰老师的<ES6 标准入门>第2版,ps:之前在阮一峰老师的官网看过电子版,感觉干货满满,所以就买了纸质版:当看到第16章第4节 'Promise.p ...
- C语言进制转换的一个小错误
今天学妹问了一个问题,问题是这样的 有以下程序 #include <stdio.h> void main(){ int m=0256,n=256; printf("%o %o& ...
- 如何添加自己封装的代码到Cocoapod
这两天学习了如何添加自己封装的代码到Cocoapod中 以下是我这两天遇到的各种坑: 旧的方法: http://my.oschina.net/u/727843/blog/392784 这个看看可以大 ...
- STL的空间配置器std_alloc 笔记
STL的空间配置器std_alloc 笔记 C++的内存分配基本操作是 ::operator new(),内存释放是 ::operator delete(),这里个全局函数相当于C的malloc和fr ...
- angular js 和 dajango 标签{{}} 冲突
问题描述: 如果在django的模板中使用{{ }},不会被angularjs 识别. 解决办法: >1.5 的django中,将需要angularjs解释的{{expression}}放在 v ...
- thinkphp中find()和select()的区别
1.find()是查找符合条件的第一条数据,返回的是一个一维数组: select()是查找符合条件的所有的数据,返回的是一个二维数组: 2.以下案例 $tech=M('techlevel','HR_C ...
- JavaWeb 环境搭建
环境搭建 JDK7 Java基本开发工具包 安装(目录[不要使用中文和空格].JDK+JRE) 配置环境变量[JAVA_HOME.path.classpath] 2. Tomcat7 提 ...