【2018沈阳赛区网络预选赛J题】Ka Chang【分块+DFS序+线段树】
题意
给出一个有根树(根是1),有n个结点。初始的时候每个结点的值都是0.下面有q个操作,操作有两种,操作1.将深度为L的点的值全部增加X。操作2.查询以x为根的子树的结点值得和。
其中N,Q<=1e5
分析
一看这种没有办法直接用数据结构解决得问题就要考虑分块。这个题其实也不算是分块,应该是用了分块的思想进行分类而已。场上也一直在想分块但是可能是自己太菜了,赛后看了题解补的。
分块最重要的就是算时间复杂度啊。我们按照每一层的结点数进行分类。节点数>block的为第一类,节点数<=为第二类。
对于第二类,每次修改操作我们暴力修改每个结点的影响值,因为涉及线段树或者树状数组的操作,时间复杂度为O(q*block*logn)。而每次通过线段树查询都是logn的
对于第一类,当修改的时候直接记录这一层被增加了多少,O(1)修改,然后查询的时候只需要枚举第二类的每一层,然后以这个结点为根节点的子树中属于这一层的节点数*这一层增加的值。这里的时间复杂度是O(q*n/block)
我们需要预处理出每个结点的子树中属于第一类层的节点数各有多少。这里我用的办法就是直接暴力。枚举每个点,如果它所在的层是第一类,那么更新它所有的父节点。这里的时间复杂度很容易被认为是O(n^2)(所以我一直不打敢写)。但是我们仔细分析一下发现它远远小于O(n^2)。因为最多有n/block层,所以这里的时间复杂度是O(n*n/block)
先不考虑预处理,只看操作的时间复杂度是O(q*block*logn+q*n/block).根据均值不等式最小是O(q*2*sqrt(nlogn)),当且仅当block取sqrt(n/logn)。这时候预处理的时间复杂度是O(n*sqrt(n*logn))经过计算时可以承受的(因为只有单组数据)。
这种题目时间复杂度计算明白以后写起来还是很好写的
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <vector> using namespace std;
typedef long long LL;
const int maxn=+;
int head[maxn],to[maxn*],Next[*maxn],Fa[maxn];
int n,q,sz,block,maxd;
int order[maxn],R[maxn],num,belong[maxn],L[maxn],pos[maxn]; map<int,int>M[maxn];
LL addv[maxn],sumv[*maxn];
vector<int>deep[maxn];
void init(){
sz=-;
maxd=;
num=;
// for(int i=0;i<=n;i++)M[i].clear();
// for(int i=0;i<=n;i++)deep[i].clear();
memset(head,-,sizeof(head));
// memset(addv,0,sizeof(addv));
}
void add_edge(int a,int b){
++sz;
to[sz]=b;Next[sz]=head[a];head[a]=sz;
} void dfs(int u,int fa,int dep){
maxd=max(maxd,dep);
Fa[u]=fa;
num++;
order[num]=u;L[u]=num;belong[u]=dep;pos[u]=num;
deep[dep].push_back(u);
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(v==fa)continue;
dfs(v,u,dep+);
}
R[u]=num;
}
int p,v;
void update(int o,int L,int R){
if(L==R){
sumv[o]+=v;
return ;
}
int M=L+(R-L)/;
if(p<=M)
update(*o,L,M);
if(p>M)
update(*o+,M+,R);
sumv[o]=sumv[*o]+sumv[*o+];
}
int ql,qr;
LL res;
void query(int o,int L,int R){
if(ql<=L&&qr>=R){
res+=sumv[o];
return ;
}
int M=L+(R-L)/;
if(ql<=M)
query(*o,L,M);
if(qr>M)
query(*o+,M+,R);
}
LL ask(int root){
LL res=;
map<int,int>::iterator it;
for(it=M[root].begin();it!=M[root].end();it++){
res+=(LL)it->second*addv[it->first];
}
return res;
}
int main(){
scanf("%d%d",&n,&q);
init();
int a,b,c;
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
add_edge(a,b);
}
dfs(,-,);
block=sqrt(n/log(n));
num=;
for(int i=;i<=n;i++){
if(deep[belong[i]].size()>block){
int u=i;
while(u!=-){
if(!M[u].count(belong[i]))
M[u][belong[i]]=;
else
M[u][belong[i]]++;
u=Fa[u];
}
}
}
for(int i=;i<=q;i++){
scanf("%d",&a);
if(a==){
scanf("%d%d",&b,&c);
if(deep[b].size()>block){
addv[b]+=c;
}else{
for(int j=;j<deep[b].size();j++){
int u=deep[b][j];
p=pos[u],v=c;
update(,,n);
}
}
}else{
scanf("%d",&b);
res=;
ql=L[b],qr=R[b];
query(,,n);
LL ans=res+ask(b);
printf("%lld\n",ans);
}
} return ;
}
【2018沈阳赛区网络预选赛J题】Ka Chang【分块+DFS序+线段树】的更多相关文章
- 【2018沈阳赛区网络预选赛J题】Fantastic Graph 【有上下界的网络流】
要补的题太多了导致最近没写博客(好吧是我懒) 题目链接https://nanti.jisuanke.com/t/31447 题意 给出一个二分图,问能否挑选出一些边,使得每个点的度数都在[L,R]这个 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J树分块
J. Ka Chang Given a rooted tree ( the root is node 11 ) of NN nodes. Initially, each node has zero p ...
- ACM-ICPC 2018 焦作赛区网络预赛J题 Participate in E-sports
Jessie and Justin want to participate in e-sports. E-sports contain many games, but they don't know ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J Ka Chang
Ka Chang 思路: dfs序+树状数组+分块 先dfs处理好每个节点的时间戳 对于每一层,如果这一层的节点数小于sqrt(n),那么直接按照时间戳在树状数组上更新 如果这一层节点个数大于sqrt ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树上分块+dfs序+线段树)
题意 链接:https://nanti.jisuanke.com/t/A1998 给出一个有根树(根是1),有n个结点.初始的时候每个结点的值都是0.下面有q个操作,操作有两种,操作1.将深度为L(根 ...
- ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(模拟+线段树)
https://nanti.jisuanke.com/t/30996 题意 每天增加m个灯泡,n个房间,能一次性换就换,模拟换灯泡过程.询问第几天的状态 分析 离线做,按题意模拟.比赛时线段树写挫了. ...
- 计蒜客A1998 Ka Chang (分块+dfs序+树状数组)
题意 给你一个\(1e5\)的有点权的树,有\(1e5\)个操作: 1.给第\(x\)层的点加上\(y\) 2.求以\(x\)为根的子树的点权和 思路 首先处理出层数为x的所有点 操作2一般都是用df ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang (分块思想)
题目链接:https://nanti.jisuanke.com/t/31451 题意: 给你一颗树,树上各点有初始权值,你有两种操作: 1. 给树中深度为l的点全部+x,(根节点为1,深度为0) 2. ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树状数组+分块)
Given a rooted tree ( the root is node 1 ) of N nodes. Initially, each node has zero point. Then, yo ...
随机推荐
- qqbot 配置
qqbot 配置 用起来还是挺方便的,使用 pip install qqbot 就可以. 不过找配置文件没注意,以为是在程序目前,原来是在 C:\Users\xxx.qqbot-tmp 目录. 插件可 ...
- wordpress上传文件,插件无法建立目录(根本原因解决)
刚建立的wp网站经常遇到上传图片或者下载插件“无法建立目录”的问题,肯定是权限的问题,网上大部分解决方案都是把uploads或者 plugins权限手动改成777, 有一部分人成功了,有一部分没成功, ...
- Debian初识(选择最佳镜像发布站点加入source.list文件)
选择最佳镜像发布站点加入source.list文件:netselect,netselect-apt “该将哪个Debian镜像发布站点加入source.list文件?”.有很多方法来选择镜像发布站点, ...
- java的try-with-resource机制
在java7之后可以使用try(resource1, resource2){...}这样声明之后,在try{}执行完成之后或者抛异常跳出,都会调用reouce1.close(),resource2.c ...
- 12.Python使用requests发送post请求
1.我们使用postman进行接口测试的时候,发现POST请求方式的编码有3种,具体的编码方式如下: A:application/x-www-form-urlencoded ==最常见的post提交数 ...
- redis+php实现微博功能(一)
(一).微博功能概况 微博用户账号注册 微博用户登录 微博发布 添加微博好友(粉丝) 微博推送 微博冷数据写入mysql数据库 (二).redis数据结构设计 这节分享微博用户注册与登录:我们完全采用 ...
- celery制作定时任务
celery参考地址:http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#starting-the-schedu ...
- Unit01: jQuery概述 、 jQuery选择器 、 jQuery操作DOM
Unit01: jQuery概述 . jQuery选择器 . jQuery操作DOM 使用jQuery放大字体: <!DOCTYPE html> <html> <head ...
- 基于Spring Boot和Spring Cloud实现微服务架构
官网的技术导读真的描述的很详细,虽然对于我们看英文很费劲,但如果英文不是很差,请选择沉下心去读,你一定能收获好多.我的学习是先从Spring boot开始的,然后接触到微服务架构,当然,这一切最大的启 ...
- laravel的model例子
5里面直接artisan建立model ./artisan make:model MyModel 找到MyModel,改成下面这样 <?php namespace App; use Illumi ...