gym 100589A queries on the Tree 树状数组 + 分块
题目大意:
给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重。
思路:
思考后发现,以dfs序建立树状数组,方便查询,不方便修改,以bfs序建立树状数组,方便修改,不方便查询。
在计算子树权重的时候发现,如果我能算出 所有层 属于这棵子树的 点数*对应层需要加上的val,那么就得到了这棵树的总权重。但是显然暴力统计点数会超时,于是我们把用一个分块的想法,对于一层来说,如果这层的总点数小于块的大小,就暴力树状数组修改,如果大于快,就用一个数组记录一下修改的值,并且把这一层保存到一个large的vector里面,表示这些层我是没有计算到树状数组里的。
在查询的时候,先用dfs序弄出每一个节点的(l,r)区间,统计树状数组里的值,然后对large里面的层来说,由于我实现记录好了每个层节点的dfs序号,并且是按照从小打到的顺序的,对于每个large层来说,只要是大于等于序号 l ,小于等于序号 r 的节点都属于这个点,所以用upper_bound和lower_bound来计算就得到了点数,乘以每一层对应的val就可以了。
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define CLR(a,b) memset(a,b,sizeof(a))
#define PI acos(-1)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=;
struct edge{
int to,Next;
}e[maxn];
int n,m;
int tot,head[maxn],u,v,L[maxn],R[maxn],time,dfn[maxn];
ll val[maxn];
int limit;
ll c[maxn];
inline int lowbit(int x){
return x&(-x);
}
inline void add(int x,ll val){
while(x<=n){
c[x]+=val;
x+=lowbit(x);
}
}
inline ll getsum(int x){
ll ans=;
while(x>)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
vector<int >large;//大的层
vector<int >pos[maxn];//每一层有哪些点
inline void init(){
CLR(head,-),tot=,time=;
large.clear();
CLR(c,),CLR(val,);
for(int i=;i<=n;i++){
pos[i].clear();
}
limit=; }
inline void addv(int u,int v){
e[++tot]={v,head[u]};
head[u]=tot;
} inline void dfs(int u,int deep){
dfn[u]=++time;
pos[deep].push_back(time);
L[u]=time;
for(int i=head[u];i!=-;i=e[i].Next)
{
int v=e[i].to;
dfs(v,deep+);
}
R[u]=time;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
addv(u,v);
}
dfs(,);
for(int i=;i<=n;i++)
{
if(pos[i].size()>limit)
{
large.push_back(i);
}
}
int dis,x,op;
ll y;
while(m--)
{
scanf("%d",&op);
if(op==)
{
scanf("%d%lld",&dis,&y);
if(pos[dis].size()<=limit)
{
for(int i=;i<pos[dis].size();i++)
{
add(pos[dis][i],y);
}
}
else{
val[dis]+=y;
}
}else{
scanf("%d",&x);
// printf("l:%d r:%d\n",L[x],R[x]);
ll ans=getsum(R[x])-getsum(L[x]-);
for(int i=;i<large.size();i++)
{
ans+=val[large[i]]*(upper_bound(pos[large[i]].begin(),pos[large[i]].end(),R[x])-lower_bound(pos[large[i]].begin(),pos[large[i]].end(),L[x]));
}
printf("%lld\n",ans);
}
} }
} /*
1 6
1 0 1
2 1
1 0 3
2 1
1 0 1
1 0 1
*/
2.0 s
512 MB
standard input
standard output
You are given a directed tree with N with nodes numbered 1 to N and rooted at node 1. Each node initially contains 0 coins.
You have to handle a total of M operations:
- 1 L Y : Increase by Y the coins of all nodes which are at a distance L from root.
- 2 X : Report the sum of coins of all nodes in subtree rooted at node X.
First line contains N and M. Each of the next N - 1 lines contains u and v denoting directed edge from node numbered u to v.
Each of the next M lines contain queries of either Type 1 or 2.
For each query of Type 2, print the required sum.
Constraints
- 1 ≤ N ≤ 105
- 1 ≤ M ≤ 104
- 0 ≤ L ≤ Maximum height of tree
- 0 ≤ Y ≤ 109
- 1 ≤ X, u, v ≤ N
5 4
1 2
1 3
3 4
3 5
1 1 2
1 2 3
2 3
2 1
8
10
In first update nodes 2 and 3 are increased by 2 coins each.
In second update nodes 4 and 5 are increased by 3 each.
gym 100589A queries on the Tree 树状数组 + 分块的更多相关文章
- BZOJ_2141_排队_树状数组+分块
BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...
- 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分
题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...
- HDU3333 Turing Tree 树状数组+离线处理
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- POJ 3321 Apple Tree(树状数组)
Apple Tree Time Limit: 2000MS Memory Lim ...
- HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)
题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
- POJ--3321 Apple Tree(树状数组+dfs(序列))
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 22613 Accepted: 6875 Descripti ...
- POJ 3321:Apple Tree 树状数组
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 22131 Accepted: 6715 Descr ...
- E - Apple Tree(树状数组+DFS序)
There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. ...
- POJ3321 Apple Tree(树状数组)
先做一次dfs求得每个节点为根的子树在树状数组中编号的起始值和结束值,再树状数组做区间查询 与单点更新. #include<cstdio> #include<iostream> ...
随机推荐
- vector的简单用法
vector是C++中容器的一种,与普通的数组相比,它可以动态的增长,而且还有封装了用于顺序表的操作的方法. 使用vector定义了容器之后,如果定义了容器的大小,则可以在大小范围之内直接使用数组的方 ...
- 268. Missing Number序列中遗失的数字
[抄题]: Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is ...
- ubuntu 安装两个版本的Anaconda
1.下载anaconda2/anaconda3,下载地址:https://www.anaconda.com/download/#linux,anaconda官网如下所示,选择对应版本下载. 2.使用如 ...
- How to install Freemind 1.0.1 to Ubuntu 14
安装了Freemind0.9后发现不能打开windows的1.0.1保存的*.mm文件,便对版本开始升级. 1. 从http://freemind.sourceforge.net/wiki/index ...
- LINUX 查看CUP温度
在Linux下可以通过lm_sensors来查看CPU的温度(当然你的硬件首先要支持),要使用这个功能要有内核相关模块(比如I2C)的支持,下面说一下操作方法: 先看一下你的机器上是否安装了lm_se ...
- 第八课 ROS的空间描述和变换
1.tf的实际应用 1)在机器人的配置中 从上面可以看出激光雷达中心距离机器人底座的中心有20cm,激光雷达的中心距机器人底座中心有10cm,如果激光雷达在障碍物前面0.3米,那么机器人底座离障碍物多 ...
- ZendStudio 代码调试
F5.单步调试进入函数内部(单步进入)F6.单步调试不进入函数内部(跳过)F7.由函数内部返回到调用处(跳出) F8.一直执行到下一个断点Ctrl+F2:结束调试
- ubuntu 14.04编译安装xen4.4总结
1. 安装环境 操作系统:ubuntu14.04 xen版本:xen4.4 2. 依赖包的安装 在安装xen之前先进行依赖包的安装,在不停得尝试之后,总结出以下需要安装的依赖包. sudo apt-g ...
- 编写高质量代码改善C#程序的157个建议——建议49:在Dispose模式中应提取一个受保护的虚方法
建议49:在Dispose模式中应提取一个受保护的虚方法 在标准的Dispose模式中,真正的IDisposable接口的Dispose方法并没有做实际的清理工作,它其实是调用了下面的这个带bool参 ...
- Linux下为Eclipse安装hadoop插件
前提条件:在Linux系统中已经安装好了jdk和hadoop 本文的安装环境:1.arch Linux 2. hadoop1.0.1本地伪分布模式安装 3. Eclipse 4.5 1. 下载Ecl ...