沈阳网络赛J-Ka Chang【分块】【树状数组】【dfs序】
Given a rooted tree ( the root is node 11 ) of NN nodes. Initially, each node has zero point.
Then, you need to handle QQ operations. There're two types:
1\ L\ X1 L X: Increase points by XX of all nodes whose depth equals LL ( the depth of the root is zero ). (x \leq 10^8)(x≤108)
2\ X2 X: Output sum of all points in the subtree whose root is XX.
Input
Just one case.
The first lines contain two integer, N,QN,Q. (N \leq 10^5, Q \leq 10^5)(N≤105,Q≤105).
The next n-1n−1 lines: Each line has two integer aa,bb, means that node aa is the father of node bb. It's guaranteed that the input data forms a rooted tree and node 11 is the root of it.
The next QQ lines are queries.
Output
For each query 22, you should output a number means answer.
样例输入复制
3 3
1 2
2 3
1 1 1
2 1
2 3
样例输出复制
1
0
题目来源
题意:
有一棵树 两种操作
一种是 将深度为i的所有节点的值加x
一种是 求以x为根的子树的所有节点之和
题解:
比赛的时候想到线段树 + dfs序了
也想到了将深度相同的节点用数组存
但是后面担心没办法维护修改 就有点不太会了
今天看题解的时候看到有一个人说 “ 一看这种没有办法直接用数据结构解决得问题就要考虑分块。”【学到了学到了】
对于同一深度设一个阈值limit,若这一深度中结点的个数>limit,则不实际进行更改,而是用一个数组来标记,因为>limit的层数不会太多,所以可以直接暴力枚举所有超越阈值的层数对于答案的贡献,同时二分答案即可。
节点数>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))经过计算时可以承受的(因为只有单组数据)。
// ConsoleApplication3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// //#include "pch.h"
#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<set>
#include<cmath>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<stack> #define inf 0x3f3f3f3f using namespace std; typedef long long LL; const int maxn = 1e5 + ;
int n, q;
struct edge{
int v, nxt;
}e[maxn << ];
int head[maxn], cnt;
int cntid, st[maxn], ed[maxn];
vector<int>dep[maxn];
vector<int>large;
LL sum[maxn], num[maxn]; void init()
{
memset(head, -, sizeof(head));
memset(sum, , sizeof(sum));
memset(num, , sizeof(num));
cnt = ;
cntid = ;
} void addedge(int u, int v)
{
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt++;
} void dfs(int u, int fa, int depth)
{
st[u] = ++cntid;
dep[depth].push_back(cntid);
for(int i = head[u]; i != -; i = e[i].nxt){
int v = e[i].v;
if(v != fa){
dfs(v, u, depth + );
}
}
ed[u] = cntid;
} void add(int pos, LL x)
{
while(pos <= n){
sum[pos] += x;
pos += (pos & -pos);
}
} LL query(int pos)
{
LL ans = ;
while(pos){
ans += sum[pos];
pos -= (pos & -pos);
}
return ans;
} int main()
{
init();
scanf("%d%d", &n, &q);
for(int i = ; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(, , );
//cout<<"y"<<endl;
int block = ceil(sqrt(n));
for(int i = ; i < n; i++){//节点大于阈值的层
if(dep[i].size() > block){
large.push_back(i);
}
} while(q--){
int op;
scanf("%d", &op);
if(op == ){
int d;
LL x;
scanf("%d%lld", &d, &x);
if(dep[d].size() > block){
num[d] += x;
}
else{
for(int i = ; i < dep[d].size(); i++){
add(dep[d][i], x);//暴力修改
}
}
}
else{
int x;
scanf("%d", &x);
LL ans = query(ed[x]) - query(st[x] - );//查询子树中属于第二类的节点的部分
for(int i = ; i < large.size(); i++){
//查询所有第一类的层数中 属于这棵子树的节点 乘以盖层的修改值
ans += (upper_bound(dep[large[i]].begin(), dep[large[i]].end(), ed[x]) - lower_bound(dep[large[i]].begin(), dep[large[i]].end(), st[x])) * num[large[i]];
}
printf("%lld\n", ans);
}
} return ;
}
沈阳网络赛J-Ka Chang【分块】【树状数组】【dfs序】的更多相关文章
- [bzoj4765]普通计算姬(分块+树状数组+DFS序)
题意 给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 ...
- BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...
- 2019-ACM-ICPC-徐州站网络赛- I. query-二维偏序+树状数组
2019-ACM-ICPC-徐州站网络赛- I. query-二维偏序+树状数组 [Problem Description] 给你一个\([1,n]\)的排列,查询\([l,r]\)区间内有多少对 ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- Trace 2018徐州icpc网络赛 (二分)(树状数组)
Trace There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
- HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)
Tree chain problem Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- 【BZOJ3653】谈笑风生 离线+树状数组+DFS序
[BZOJ3653]谈笑风生 Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”. ? 设a 和 ...
- BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
题目大意: 给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过 好神的一道题 对$n$个大串建出广义$SAM$,建出$parent$树 把字符串$s$放到$SAM$里跑, ...
- luogu SP8093 后缀自动机+树状数组+dfs序
这题解法很多,简单说几个: 1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力. 3. 建立后缀树后在 $ ...
随机推荐
- vector push_back报错
场景:定义了一个结构体,包含一个vector的成员变量,在给这个vTQ push_back数据的时候报错. typedef struct tag_TQInfo { int iTime; int iMa ...
- ubuntu下android源码的下载(最新)
在ubuntu下下载android源码我断断续续搞了好几个月,希望大家不要向我学习啊!一次性搞定! 这里给大家一些建议啊,如果是看书的话看下书的出版日期,超过一年的基本上失效,网上的也是,特别是在国内 ...
- JS中document对象详解
转自:http://www.cnblogs.com/andycai/archive/2010/06/29/1767351.html 对象属性 document.title //设置文档标题等价于HTM ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- js使用正则表达式从url中获取参数值
//从url中获取参数值 function getvl(name) { var reg = new RegExp("(^|\\?|&)"+ name +"=([^ ...
- path与classpath的差别
1.path的作用 path是系统用来指定可运行文件的完整路径.即使不在path中设置JDK的路径也可运行JAVA文件,但必须把完整的路径写出来,如C:\Program Files\Java\ ...
- RGB 颜色对照表
R G B 值 R G B 值 R G B 值 黑色 0 0 0 #000000 黄色 255 255 0 #FFFF00 浅灰蓝色 176 224 230 #B0E0E6 象牙黑 41 36 ...
- vs2013配置opencv3.2.0
工具/原料 l VS2013 l OpenCV3.20http://jaist.dl.sourceforge.net/project/opencvlibrary/opencv-win/3.2.0/op ...
- java.util.logging.Logger使用具体解释
java.util.logging.Logger不是什么新奇东西了,1.4就有了,但是由于log4j的存在,这个logger一直沉默着,事实上在一些測试性的代码中,jdk自带的logger比log4j ...
- iOS 开发 - iOS 8 以后使用UIAlertController的使用
最近在写项目的时候,发现使用alertview和actonsheet会报警告,所以就查了一下,发现ios 9 以后会使用UIAlertController来进行操作, 具体代码如下: 1.声明 #im ...