沈阳网络赛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. 建立后缀树后在 $ ...
随机推荐
- eclipse下载,安装,JDk环境配置教程(多图)
第一步:下载eclipse,并安装. 下载链接:http://www.eclipse.org/downloads/ 点击 Download Packages; 根据自己的系统选择32位还是64位的,点 ...
- [转]Git学习笔记与IntelliJ IDEA整合
Git学习笔记与IntelliJ IDEA整合 一.Git学习笔记(基于Github) 1.安装和配置Git 下载地址:http://git-scm.com/downloads Git简要使用说明:h ...
- LoadRunner 调用dll方法
本文主要介绍简单DLL的编写方法及在LoadRunner中局部调用与全局调用DLL方法. 1.动态链接库的编写 在Visual C++6.0开发环境下,打开FileNewProject选项,可以选择W ...
- [译]Unity3D内存管理——对象池(Object Pool)
原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...
- java图形化Swing教程(一)
与多线程.泛型等不同,Swing主要在于使用. 以下主要放代码和凝视.少说话. (一)基本框架 package Swing; import java.awt.*; import javax.swing ...
- MFC 小知识总结五
1 移动无标题对话框 响应WM_NCHITTEST 消息 [cpp] view plaincopy LRESULT CTimeJishiDlg::OnNcHitTest(CPoint point) ...
- 关于直播学习笔记-002-Red5 & Sewise Player & Wirecast
一.工具软件 [1]. 视频采集端 Red5 Demo:http://192.168.31.107:5080/demos/simpleBroadcaster.html Telestream:Wirec ...
- 【RF库Collections测试】Get Dictionary Values
Name:Get Dictionary ValuesSource:Collections <test library>Arguments:[ dictionary ]Returns val ...
- Linux mysqladmin 命令
mysqladmin命令可以用来设置或修改 MySQL 密码,常见用法如下: [root@localhost ~]$ mysqladmin -uroot password 'newPass' # 在无 ...
- m2014-architecture-imgserver->Lighttpd +mod_mem_cache的效果简直太好了
公司的图片服务器一直以来负载都比较高,原因是图片比较分散而且比较小.经常把iowait搞的特别的高.但是只有一台机器也法用squid,经测试squid和apache在同一台机器效果会很糟糕的.因为sq ...