计蒜客 31451 - Ka Chang - [DFS序+树状数组][2018ICPC沈阳网络预赛J题]
题目链接:https://nanti.jisuanke.com/t/31451
Given a rooted tree ( the root is node $1$ ) of $N$ nodes. Initially, each node has zero point.
Then, you need to handle $Q$ operations. There're two types:
1 L X: Increase points by $X$ of all nodes whose depth equals $L$ ( the depth of the root is zero ). ($x \leq 10^8$)
2 X: Output sum of all points in the subtree whose root is $X$.
Input
Just one case.
The first lines contain two integer, $N,Q$. ($N \leq 10^5, Q \leq 10^5$).
The next $n-1$ lines: Each line has two integer $a,b$, means that node aa is the father of node $b$. It's guaranteed that the input data forms a rooted tree and node $1$ is the root of it.
The next $Q$ lines are queries.
Output
For each query $2$, you should output a number means answer.
题意:
给出一棵 $N$ 个节点的树,初始每个节点的权值均为 $0$,接下来给出 $Q$ 个操作,有两种操作:
第一种,修改操作,对所有深度为 $L$ 的节点(根节点的深度为 $0$),权值加上 $X$;
第二种,查询操作,查询以节点 $X$ 为根节点的子树(包含节点 $X$)内所有节点的权值和。
题解:
说实话,比赛的时候,想到了DFS序+线段树的操作,但是不会搞时间复杂度卡死。然而,要知道,神仙的时间复杂度和蒟蒻的时间复杂度是不一样的。
以下根据官方题解:
设定一个层内节点数的阈值 $T$,
当第 $L$ 层的节点数 $size_L < T$ 时,用DFS序把树拍平,
修改操作,可以直接暴力枚举所有节点进行 $O\left( {\log N} \right)$ 修改,时间复杂度为 $O\left( {T\log N} \right)$;
查询操作,直接就是 $O\left( {\log N} \right)$ 区间查询。
因此,两种操作合起来的时间复杂度 $O\left( {Q \cdot T\log N} \right)$。
当第 $L$ 层的节点数 $size_L \ge T$ 时,
修改操作,存储每一层节点的权值(因为同一层内节点的权值永远是一样的),直接 $O\left( 1 \right)$ 修改;
查询操作,直接暴力枚举层,对于每一层,使用二分查找,得到属于“根为$X$的子树”的节点的个数,时间复杂度 $O\left( {\frac{N}{T}\log N} \right)$。
因此,两种操作合起来的时间复杂度 $O\left( {Q \cdot \frac{N}{T}\log N} \right)$。
因此总的时间复杂度为 $O\left( {Q\log N\left( {T + \frac{N}{T}} \right)} \right)$,所以令 $T = \sqrt N$ 最优,时间复杂度为 $O\left( {Q\sqrt N \log N} \right)$。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+; int n,q;
int T;
ll val_deep[maxn]; //存储深度为deep的节点的权值
vector<int> Node_deep[maxn]; //存储深度为deep的节点的编号
vector<int> bigL; //存储节点数不小于阈值的层编号 //邻接表-st
struct Edge{
int u,v;
Edge(int u=,int v=){this->u=u,this->v=v;}
};
vector<Edge> E;
vector<int> G[maxn];
void addedge(int u,int v)
{
E.push_back(Edge(u,v));
G[u].push_back(E.size()-);
}
//邻接表-ed //dfs序-st
int dfs_clock=;
int in[maxn],out[maxn];
void dfs(int now,int dep)
{
in[now]=++dfs_clock;
Node_deep[dep].push_back(in[now]);
for(int i=;i<G[now].size();i++)
{
int nxt=E[G[now][i]].v;
dfs(nxt,dep+);
}
out[now]=dfs_clock;
}
//dfs序-ed struct _BIT{
int N;
ll C[maxn];
int lowbit(int x){return x&(-x);}
void init(int n) //初始化共有n个点
{
N=n;
for(int i=;i<=N;i++) C[i]=;
}
void add(int pos,ll val) //在pos点加上val
{
while(pos<=N)
{
C[pos]+=val;
pos+=lowbit(pos);
}
}
ll sum(int pos) //查询1~pos点的和
{
ll ret=;
while(pos>)
{
ret+=C[pos];
pos-=lowbit(pos);
}
return ret;
}
}BIT; int main()
{
cin>>n>>q;
T=((n>)?(int)sqrt(n):n);
for(int i=;i<n;i++)
{
int par,son; scanf("%d%d",&par,&son);
addedge(par,son);
} dfs(,); for(int dep=;dep<=n;dep++)
{
if(Node_deep[dep].size()>=T) bigL.push_back(dep);
} BIT.init(n);
memset(val_deep,,sizeof(val_deep));
for(int i=;i<=q;i++)
{
int type; scanf("%d",&type);
if(type==)
{
int L,X; scanf("%d%d",&L,&X);
if(Node_deep[L].size()<T)
for(int k=;k<Node_deep[L].size();k++) BIT.add(Node_deep[L][k],(ll)X);
else
val_deep[L]+=X;
}
else
{
int X; scanf("%d",&X);
ll ans=BIT.sum(out[X])-BIT.sum(in[X]-);
for(int k=;k<bigL.size();k++)
{
int dep=bigL[k];
int L=lower_bound(Node_deep[dep].begin(),Node_deep[dep].end(),in[X])-Node_deep[dep].begin();
int R=upper_bound(Node_deep[dep].begin(),Node_deep[dep].end(),out[X])-Node_deep[dep].begin();
ans+=(R-L)*val_deep[dep];
}
printf("%lld\n",ans);
}
}
}
评测结果:
可以看到,名字叫卡常的题目是最不卡常的。
计蒜客 31451 - Ka Chang - [DFS序+树状数组][2018ICPC沈阳网络预赛J题]的更多相关文章
- 计蒜客 青出于蓝胜于蓝(dfs序+树状数组)
题目描述 武当派一共有 n 人,门派内 n 人按照武功高低进行排名,武功最高的人排名第 1,次高的人排名第 2,... 武功最低的人排名 第 n.现在我们用武功的排名来给每个人标号,除了祖师爷,每个人 ...
- 计蒜客A1998 Ka Chang (分块+dfs序+树状数组)
题意 给你一个\(1e5\)的有点权的树,有\(1e5\)个操作: 1.给第\(x\)层的点加上\(y\) 2.求以\(x\)为根的子树的点权和 思路 首先处理出层数为x的所有点 操作2一般都是用df ...
- HDU 3887:Counting Offspring(DFS序+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
- [BZOJ1103][POI2007]大都市meg dfs序+树状数组
Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...
- 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)
传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...
随机推荐
- Android沉浸式状态栏兼容4.4手机的实现
一.概述 最近注意到QQ新版使用了沉浸式状态栏,ok.先声明一下:本篇博客效果下图: 关于这个状态栏变色究竟叫「Immersive Mode」/「Translucent Bars」有兴趣能够去 为什么 ...
- Dubbo -- 系统学习 笔记 -- API参考手册
Dubbo -- 系统学习 笔记 -- 目录 API参考手册 配置API 注解API 模型API 上下文API 服务API API参考手册 Dubbo的常规功能,都保持零侵入,但有些功能不得不用API ...
- HTML5的一个写下拉文本框标签
新的HTML5有个标签,能够下拉的文本框 代码如下 <input list="browsers"> <datalist id="browsers&quo ...
- express安装及使用(windows系统)
npm install express //安装express命令 npm install express-generator -g //Express 应用生成器,通过应用生成器工具 express ...
- Java Cookie工具类,Java CookieUtils 工具类,Java如何增加Cookie
Java Cookie工具类,Java CookieUtils 工具类,Java如何增加Cookie >>>>>>>>>>>>& ...
- CouchDB 未授权访问漏洞
0x00 CouchDB安装 CouchDB官方网站:http://couchdb.apache.org/ 一路Next直到完成安装,打开浏览器并访问以下链接:http://127.0.0.1:598 ...
- MongoDB(六)-- 集群搭建
一.集群介绍 sharding通过将数据集分布于多个也称作分片(shard)的节点上来降低单节点的访问压力.每个分片都是一个独立的数据库,所有的分片组合起来构成一个逻辑上的完整意义的数据库.因此,分片 ...
- java.util.concurrent.RejectedExecutionException 线程池饱和
java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPoli ...
- 分布式计算开源框架Hadoop入门实践
目录(?)[+] Author :岑文初 Email: wenchu.cenwc@alibaba-inc.com msn: cenwenchu_79@hotmail.com blog: http:// ...
- 理解Java的反射与内省及其区别
java的内省机制和反射机制什么区别 内省操作只针对JavaBean,只有符合JavaBean规则的类的成员才可以采用内省API进行操作....而反射则不同,一个类的所有成员都可以进行反射操作. 内省 ...