博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NewTrain6 A (bzoj3631) 松鼠的新家 树剖/lca
阅读量:4361 次
发布时间:2019-06-07

本文共 5086 字,大约阅读时间需要 16 分钟。

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  
Memory Limit: 128 MB
Submit: 2560  
Solved: 1357
[ ][ ][ ]

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

Output

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

Sample Input

5
1 4 5 3 2
1 2
2 4
2 3
4 5

Sample Output

1
2
1
2
1

HINT

2<= n <=300000

 

题目大意:给定一棵n个节点的树和一个1~n的排列ai,对于每一个i,给从ai到ai+1的路径上除了起点以外的点都加上1,求每个点最终的值

 

题解:

看到题就感觉像树剖,于是就直接套板子上了。每次对于一条链来说,给左端点加上1,右端点的下一位减去1,最后做一个前缀和。注意每次是不给起点+1的,因此最后给除了a1以外的点全部-1就好了

 

代码:

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 #include
21 #include
22 #include
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32 #include
33 #include
34 #include
35 #include
36 #include
37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43 #include
44 #include
45 #include
46 #include
47 #include
48 #include
49 #include
50 #include
51 #include
52 #include
53 #include
54 #include
55 #include
56 using namespace std; 57 58 typedef long long ll; 59 60 #define pb push_back 61 #define mp make_pair 62 #define x first 63 #define y second 64 65 const ll inf=2147483647; 66 67 // 68 69 ll read() 70 { 71 ll x=0,f=1; 72 char ch=getchar(); 73 while(ch<'0'||ch>'9') 74 { 75 if(ch=='-')f=-1; 76 ch=getchar(); 77 } 78 while(ch>='0'&&ch<='9') 79 { 80 x=x*10+ch-'0'; 81 ch=getchar(); 82 } 83 return x*f; 84 } 85 86 void print(ll x) 87 { 88 if(x<0)putchar('-'),x=-x; 89 short a[20]= {},sz=0; 90 while(x>0)a[sz++]=x%10,x/=10; 91 if(sz==0)putchar('0'); 92 for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]); 93 } 94 95 const ll mod=1e9+7; 96 97 int n; 98 int a[333333]; 99 vector
adj[333333];100 101 int fa[333333];102 int dep[333333];103 int sz[333333];104 int son[333333];105 int tp[333333];106 int num[333333];107 int rnk[333333];108 int cnt;109 110 void dfs1(int nw,int pa,int d){111 fa[nw]=pa;112 dep[nw]=d;113 sz[nw]=1;114 for(int i=0;i
b) swap(a,b);155 ans[a]++;156 ans[b+1]--;157 }158 159 void update_path(int x,int y){160 int fx=tp[x],fy=tp[y];161 while(fx!=fy){162 if(dep[fx]>=dep[fy]){163 add(num[fx],num[x]);164 x=fa[fx];165 }166 else{167 add(num[fy],num[y]);168 y=fa[fy];169 }170 fx=tp[x];171 fy=tp[y];172 }173 add(num[x],num[y]);174 }175 176 int main(){177 //freopen("in","r",stdin);178 n=read();179 for(int i=1;i<=n;i++)180 a[i]=read();181 for(int i=1;i
View Code

 

 

 

然后就发现自己做烦了。

我都想到了给左端点加1右端点减1了,就没想到树上也能这样做

每次操作,给两个端点都加上1,然后给他们的lca减去1,lca的父亲也减去1,然后在dfs一下,每个点的权值加上他的儿子们的权值。注意,输出时所有的点的权值-1,原因同上

 

代码:

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 #include
21 #include
22 #include
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32 #include
33 #include
34 #include
35 #include
36 #include
37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43 #include
44 #include
45 #include
46 #include
47 #include
48 #include
49 #include
50 #include
51 #include
52 #include
53 #include
54 #include
55 #include
56 using namespace std; 57 58 typedef long long ll; 59 60 #define pb push_back 61 #define mp make_pair 62 #define x first 63 #define y second 64 65 const ll inf=2147483647; 66 67 // 68 69 ll read() 70 { 71 ll x=0,f=1; 72 char ch=getchar(); 73 while(ch<'0'||ch>'9') 74 { 75 if(ch=='-')f=-1; 76 ch=getchar(); 77 } 78 while(ch>='0'&&ch<='9') 79 { 80 x=x*10+ch-'0'; 81 ch=getchar(); 82 } 83 return x*f; 84 } 85 86 void print(ll x) 87 { 88 if(x<0)putchar('-'),x=-x; 89 short a[20]= {},sz=0; 90 while(x>0)a[sz++]=x%10,x/=10; 91 if(sz==0)putchar('0'); 92 for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]); 93 } 94 95 const ll mod=1e9+7; 96 97 int fa[21][333333]; 98 int n; 99 int a[333333];100 vector
adj[333333];101 int tag[333333];102 int dep[333333];103 104 void dfs(int nw,int pa){105 // cout<
<<' '<
<
=0;i--){119 if(dep[fa[i][x]]>dep[y]) x=fa[i][x];120 }121 if(dep[x]>dep[y]) x=fa[0][x];122 if(x==y) return x;123 for(int i=19;i>=0;i--){124 if(fa[i][x]!=fa[i][y])125 x=fa[i][x],y=fa[i][y];126 }127 return fa[0][x];128 }129 130 void doit(int x,int y){131 int z=lca(x,y);132 //cout<
<<' '<
<<' '<
<
View Code

 

 

 

转载于:https://www.cnblogs.com/nflslzt/p/8647787.html

你可能感兴趣的文章
组件化网页开发 3步骤 / 20门课
查看>>
LeetCode 896. 单调数列(Monotonic Array)
查看>>
HDU 6318 - Swaps and Inversions [2018杭电多校联赛第二场 J](离散化+逆序对)
查看>>
千万级高性能长连接网关揭秘
查看>>
shell编程基础(5)---循环指令
查看>>
团队贡献分分配
查看>>
dumpsys, traceView调试命令
查看>>
Linux自己主动挂载第二块硬盘分区
查看>>
<html>
查看>>
Ajax请求设置csrf_token
查看>>
用VMware 8安装Ubuntu 12.04详细过程(图解)
查看>>
在浏览器输入网址,Enter之后发生的事情
查看>>
js和jquery修改背景颜色的区别
查看>>
使用AD画PCB的技能总结(纯属个人笔记,请大神多多指导)
查看>>
HDU 1232 畅通工程(最小生成树+并查集)
查看>>
idea提交项目到码云上
查看>>
数组迭代
查看>>
[BeiJing2010组队]次小生成树Tree
查看>>
一步一步学asp.net_Lucene.net站内搜索
查看>>
【WPF系列】Textbox
查看>>