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 ;
}

最新文章

  1. ReactiveCocoa代码实践之-RAC网络请求重构
  2. response设置相应头的方法
  3. linux curl 下载jdk
  4. iOS开源项目MobileProject功能点介绍
  5. MySql 定时备份数据库
  6. 对git认识
  7. UDP protocol
  8. js 获取浏览器版本号
  9. PHP临时文件session的分级存储与定期删除
  10. Welcome to JimmyCheung&#39;s blog!
  11. iOS在UITableViewController里使用UISearchDisplayController报错&quot;[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:]&quot;
  12. 什么是野指针?(What is a wild pointer?)
  13. Android面试经验1
  14. 几种在shell命令行中过滤adb logcat输出的方法
  15. 原创 :nfs软件服务利用ansible实现一键化部署
  16. 20175234 2018-2019-2 《Java程序设计》第七周学习总结
  17. IntelliJ IDEA执行maven 跳过test
  18. 一字一句的搞懂vue-cli之vue webpack template配置
  19. jQuery之JSP加载JS文件不起作用的有效解决方法
  20. Python接口自动化--URL参数的编码和解码 6

热门文章

  1. 免费在线生成彩色带logo的个性二维码
  2. OC对象之旅 weak弱引用实现分析
  3. 提高java编程质量 - (二)取余用偶判断,不要用奇判断
  4. 解决其他浏览器没有propertychange事件
  5. 常见web容器
  6. 表连接查询的顺序和where子句条件的前后顺序会影响sql的性能么
  7. ffmpeg参数说明
  8. java 得到uuid并处理
  9. sublime 设置字体
  10. 转换编码,将Unicode编码转换成可以浏览的utf-8编码