树链剖分板子题

先说点别的

小熊维尼啊,嘿嘿嘿。

写题经历

悲惨命运:树剖调了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]松鼠的新家】的更多相关文章

  1. 洛谷 P3258 [JLOI2014]松鼠的新家 题解

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  2. P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...

  3. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  4. 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

    [题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...

  5. 洛谷P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  6. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  7. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  8. P3258 [JLOI2014]松鼠的新家题解

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有\(n\)个房间,并且有\(n-1\)根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树& ...

  9. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

    题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...

  10. 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...

随机推荐

  1. node express 应用笔记关键点

    1.处理客户端 POST数据(标签 <form>), req.body 对象 app.js var bodyParser = require('body-parser'); ... ... ...

  2. 软件版本 Alpha、Beta、Rc

    软件版本的周期 α.β.γ 表示软件测试中的三个阶段 α :第一阶段,内部测试使用 β: 第二阶段,消除了大部分不完善的地方,仍可能存在漏洞,一般提供给特定的用户使用 γ: 第三阶段,产品成熟,个别地 ...

  3. techiediaries网站的Laravel 6系列教程

    Laravel 6 Tutorial & New Features - Build a CRM [PART 1] Laravel 6 REST API CRUD Tutorial - Buil ...

  4. 解决PLSQL 查询后显示中文为问号(???)问题

    我的问题已解决,在装oracle的服务器上配置了下面的两个环境变量后,重启服务器,重新录入中文,在查询即可正确显示中文. 原因: 本机(装oracle的服务器)没有配置数据库字符集环境变量,或是与数据 ...

  5. C/C++网络编程7——多进程服务器端之fork函数

    通过前面几节的内容,我们已经可以实现基本的C/S结构的程序了,但是当多个客户端同时向服务器端请求服务时,服务器端只能按顺序一个一个的服务,这种情况下,客户端的用户是无法忍受的.所以虚实现并发的服务器端 ...

  6. 第六周之Hadoop学习(六)

    继续上周开启telnet的过程,这个过程发现win10上运行不了telnet的命令 原因大概在于没有开启telnet服务,从网上下载好telent服务端,安装后继续尝试是否能在win10上使用hado ...

  7. day4-1深入理解对象之创建对象

    深入理解对象 之创建对象: 工厂模式: 工厂模式虽然解决了创建\多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型) 工厂模式问题:那就是识别问题,因为根本无法 搞清楚他们到底是 ...

  8. P1045麦森数

    P1045麦森数 #include<iostream> #include <cmath> #include <cstring> const int maxn = 1 ...

  9. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:为所有表格的单元格添加边框

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. windows下 DEV-C++无法连接到pthread.h的解决办法

    参考的这个博文,原博文有图片:http://lslin.iteye.com/blog/776325 (我只是为了方便写.copy一遍) dev-C++编写C/C++程序时,非常方便轻巧,但是今天学习多 ...