【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 ...
随机推荐
- App测试工具
1.App性能测试与安全测试工具 性能测试工具:Itest(众测平台) 安全测试:Utest
- warning: backslash and newline separated by space [enabled by default]
警告:反斜杠和换行符之间多了空格. 这种问题出现在宏定义 #define,并且有多行,每行之间要用 “\” 连接起来. 解决办法:删除 “\” 后面的空格,直接紧跟回车.
- SpringMVC-Spring-Hibernate项目搭建之三-- freemarker & 静态资源整合
一. 前段目录结构如下架构如下: 二. freemarker文件配置 在 web.xml 文件中指定 spring 配置文件的位置 三. 配置springmvc-servlet.xml文件 1)配置自 ...
- java代码----大二上机考试
总结:对 冒泡排序熟悉,但不能灵活插入代码 package com.dkl; import java.io.*; import java.io.IOException; import java.uti ...
- python稀疏矩阵得到每列最大k项的值,对list内为类对象的排序(scipy.sparse.csr.csr_matrix)
print(train_set.tdm) print(type(train_set.tdm)) 输出得到: (0, 3200) 0.264940780338 (0, 1682) 0.356545827 ...
- python多标签分类模版
from sklearn.multioutput import MultiOutputClassifier from sklearn.ensemble import RandomForestClass ...
- Java-Runoob:Java Character 类
ylbtech-Java-Runoob:Java Character 类 1.返回顶部 1. Java Character 类 Character 类用于对单个字符进行操作. Character 类在 ...
- ansible之感冒药
Ansible简介安装 Ansible是一个综合的强大的管理工具,他可以对多台主机安装操作系统,并为这些主机安装不同的应用程序,也可以通知指挥这些主机完成不同的任务.查看多台主机的各种信息的状态等,a ...
- 【UVA】11464 Even Parity(枚举子集)
题目 传送门:QWQ 分析 标准的套路题. 枚举第一行,接着根据第一行递推下面的行. 时间复杂度$ O(2^n \times n^2) $ 代码 #include <bits/stdc++.h& ...
- PoJ 1595 PrimeCuts
Prime Cuts Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9339 Accepted: 3562 Descri ...