题解 P3258 【[JLOI2014]松鼠的新家】
树链剖分板子题
先说点别的
小熊维尼啊,嘿嘿嘿。
写题经历
悲惨命运:树剖调了2天,一直90分,死活不AC,调出了心病,快下课时改了一下数据范围,A了……。(刚开始数组开了800100,改1200100过了)
所以说啊,线段树必须要注意数据范围,要开4倍,不然会想傻X作者一样调出心病。(太可怕了,数据范围小了,不RE,竟然WA,评测机太可怕了QAQ)
吐槽,树链剖分题怎么都比【模板】树链剖分 简单
前置技能
1、线段树 2、树链剖分
如果你已经过了P3384 【模板】树链剖分这道题。那么这道题就是附赠的紫题哈。
思路
我们知道树链剖分支持以下操作:
1、在树中将u到v节点数值全部加一个值。
2、查询树中u到v节点的数值和
那么我们可以想到把小熊维尼去每一个房间抽象成一个一个点,那么我们要从u房间去到v房间,则要在u到v之间都放一个糖果,于是我们将松鼠它家u到v的糖果数都加1。
看到这里,想到树剖写法了吧,每一次将a[i]到a[i+1] (a数组是访问顺序)的节点加1,这个可以用树链剖分做。
查询只需要查每个点的权值就OK了。
当然还有些细节,在处理完一次修改后,终点要减1,不然会重复计算。
代码
//by:hyfhaha
#include<bits/stdc++.h>
using namespace std;
const long long maxn=1200100; //特以此纪念本人数据范围开小卡90分卡两天
int a[maxn],tree[maxn],tag[maxn],n,m,mode,x,y,z,S,cnt;
int large[maxn],seg[maxn],father[maxn],vis[maxn],dep[maxn],son[maxn],rev[maxn],top[maxn];
int Next[maxn],head[maxn],from[maxn],to[maxn],id[maxn],tot;
//********************以下线段树********************
void pushdown(int node,int begin,int end){
if(tag[node]){
int m=(begin+end)/2;
tree[node*2]+=tag[node]*(m-begin+1);
tree[node*2+1]+=tag[node]*(end-m);
tag[node*2]+=tag[node];
tag[node*2+1]+=tag[node];
tag[node]=0;
}
}
int query(int node,int begin,int end,int x,int y){
if(x<=begin&&end<=y)
return tree[node];
else{
int m=(begin+end)/2,res=0;
pushdown(node,begin,end);
if(x<=m)
res+=query(node*2,begin,m,x,y);
if(y>m)
res+=query(node*2+1,m+1,end,x,y);
return res;
}
}
void update(int node,int begin,int end,int x,int y,int val){
if(x<=begin&&end<=y){
tree[node]+=val*(end-begin+1);
tag[node]+=val;
}
else{
int m=(begin+end)/2;
pushdown(node,begin,end);
if(x<=m){
update(node*2,begin,m,x,y,val);
}
if(y>m){
update(node*2+1,m+1,end,x,y,val);
}
tree[node]=tree[node*2]+tree[node*2+1];
}
}
//********************以上线段树********************
//********************以下树链剖分********************
void dfs1(int x,int f){
large[x]=1;father[x]=f;
dep[x]=dep[f]+1;
int maxy=0;
for(int i=head[x];i!=-1;i=Next[i]){
int u=to[i],big=0;
if(u==f)continue;
dfs1(u,x);
large[x]+=large[u];
if(large[u]>maxy){son[x]=u;maxy=large[u];}
}
}
void dfs2(int x,int f){
top[x]=f;id[x]=++tot;
if(!son[x]){
return;
}
dfs2(son[x],f);
for(int i=head[x];i!=-1;i=Next[i]){
int u=to[i];
if(u!=son[x]&&u!=father[x]){
dfs2(u,u);
}
}
}
void updatelong(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<=dep[top[y]]){
update(1,1,n,id[top[y]],id[y],z);
y=father[top[y]];
}else{
update(1,1,n,id[top[x]],id[x],z);
x=father[top[x]];
}
}
if(dep[x]>dep[y])swap(x,y);
update(1,1,n,id[x],id[y],z);
}
//********************以上树链剖分********************
void add(int x,int y){ //建边
cnt++;
from[cnt]=x;to[cnt]=y;
Next[cnt]=head[x];head[x]=cnt;
}
//********************以下主程序********************
int main(){
scanf("%d",&n);S=1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n-1;i++){
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(S,0);dfs2(S,S);
for(int i=1;i<=n-1;i++){
updatelong(a[i],a[i+1],1);
updatelong(a[i+1],a[i+1],-1);//记得终点减1
}
for(int i=1;i<=n;i++)
printf("%d\n",query(1,1,n,id[i],id[i]));
}//光棍数字收场
题解 P3258 【[JLOI2014]松鼠的新家】的更多相关文章
- 洛谷 P3258 [JLOI2014]松鼠的新家 题解
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- P3258 [JLOI2014]松鼠的新家
P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家
[题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...
- 洛谷P3258 [JLOI2014]松鼠的新家
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- P3258[JLOI2014]松鼠的新家(LCA 树上差分)
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- P3258 [JLOI2014]松鼠的新家题解
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有\(n\)个房间,并且有\(n-1\)根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树& ...
- 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)
题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...
- 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
随机推荐
- 转载--centos7.4安装docker
参考博文:https://www.cnblogs.com/yufeng218/p/8370670.html 作者:风止雨歇 Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企 ...
- 小白学 Python 爬虫:Selenium 获取某大型电商网站商品信息
目标 先介绍下我们本篇文章的目标,如图: 本篇文章计划获取商品的一些基本信息,如名称.商店.价格.是否自营.图片路径等等. 准备 首先要确认自己本地已经安装好了 Selenium 包括 Chrome ...
- FreeSWITCH调用第三方TTS 使用tts_commandline
FreeSWITCH 支持调用第三方TTS命令,本身已经搭好了框架,只需要配置即可用. 下面写一下步骤,以免忘记,也希望给你带来帮助. 第一步:编译模块mod_tts_commandline,并加载. ...
- Python 正则表达式之 sub 和 subn函数的使用
re.sub() 函数的功能 re是reguler expressioin的缩写,表示正则表达式 sub 是 substitute 的缩写,表示替换: re.sub是个正则表达式方面的函数,用来实现通 ...
- PAT T1012 Greedy Snake
直接暴力枚举,注意每次深搜完状态的还原~ #include<bits/stdc++.h> using namespace std; ; int visit[maxn][maxn]; int ...
- 【原】postman设置环境变量和全局变量
一:设置环境变量 1. postman通过变换环境变量来快速变换环境地址. 2. 现可以将localhost:80信息添加至环境 3. 点击确定后,在首页可看到已添加的环境变量信息及设置的变量信息: ...
- AI基础概念
基础概念 epoch:使用训练的全部数据对模型进行一次完整的训练,被成为“一代训练”.当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一次epoch.(也就是说,所有训练样本在神经网络 ...
- Duilib定时器
转载:https://www.zhaokeli.com/article/8262.html 问题描述 直接使用系统函数定义 参数 http://www.zhaokeli.com/article/18 ...
- kafka的搭建,命令
a)kafka搭建 1.解压 2.修改配置/software/kafka_2.11-0.11.0.3/config/server.properties broker.id=0 log.dirs=/va ...
- ch3 盒模型、定位
标准盒模型.怪异盒模型 外边距叠加 当两个或者争夺垂直外边距相遇时,他们将形成一个外边距,这个外边距的高度等于两个发生叠加的外边距的高度中的较大者. 当一个元素出现在另一个元素上面时,第一个元素的底外 ...