bzoj 4765 普通计算姬(树状数组 + 分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=4765
很nice的一道题啊(可能是因为卡了n久终于做出来了
题意就是给你一棵带点权的有根树,sum(i)表示以i为根的这颗子树中所有节点的权值和。有两种操作,一种是修改某个点的权值,另一种是给出l,r,求sum(l)+sum(l+1)...+sum(r)。
首先考虑一个简单的问题,如果单求其中一个sum(i),我们可以怎样做。
很明显我们画个图
,我们可以看到每个点打上dfs序之后,每个sum就变成了一个区间,那就是单点更新,区间求和了,树状数组可以很好的解决掉。
那现在我们要解决原问题了,因为没学过树套树的玩意,所以我觉得有了上面那个东西之后,是不是可以用树套树来搞呢,查了好久,没发现什么资料,也不知道能不能搞,反正我是不会了= =,然后就尝试莫队的东西,发现更新我也不会啊,于是就傻逼了。
对大佬说了很多傻逼想法然后全被自己否决了,比如说分块一下sum啊(然而这个我自己否决了的就是最后A掉的做法),或者是,之后,突然感觉有几个不可行的合起来好像复杂度很对啊。再瞎画一下,得出了个想法。
就是上面说的分块一下sum,分块,看起来复杂度很支持啊,但是我们要考虑到,修改一个点,会使得很多个sum发生改变,我一开始否决就是把这里的复杂度算错了。那其实这里我们可以用一个贡献一样的数组来求,gx[i][j]表示修改j对第i块会产生多大影响(就是说j在第i块出现过几次),这个只需要nsqrtn就可以求出来。一开始我以为要n^2???我别是傻子吧!
但是除了整块之外的,还有其它那些,这里我们就暴力用树状数组同时维护起来,于是整体复杂度就变成了优美的nsqrtnlogn!
回忆一下貌似自己想到简化的那个问题之后,就不应该想其他东西啊,来个暴力分块就好了,不过还好总算是A掉了,另外此题答案爆longlong。。
/**************************************************************
Problem: 4765
User: caobao
Language: C++
Result: Accepted
Time:13716 ms
Memory:136396 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <time.h>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
#define ms(a,b) memset((a),(b),sizeof(a))
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> Pii;
typedef vector<int> Vi;
typedef vector<Pii> Vii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << ) - ;
const LL mod = ;
const int N = + ;
const double Pi = acos(-1.0);
const int maxn = ;
int head[maxn];
int w[maxn];
int bl[maxn];
uLL Vsum[];
int tol;
int g;
int n, m;
int root;
int sz;
struct Edge {
int to, nx;
} edge[maxn << ];
void init() {
memset(head, -, sizeof head);
}
inline void add_edge(int u, int v) {
edge[tol].to = v;
edge[tol].nx = head[u];
head[u] = tol++;
}
inline int lowbit(int x) {
return x & (-x);
}
inline void OT(uLL x) {
if(x > ) {
OT(x / );
}
putchar(x % + '');
}
uLL tree[maxn];
struct Ds {
int l, r;
} S[maxn];
inline uLL sum(int pos) {
uLL res = ;
for(; pos; pos -= lowbit(pos))res += tree[pos];
return res;
}
inline void fix(int pos, uLL x) {
x = x - sum(pos) + sum(pos - );
for(; pos < maxn; pos += lowbit(pos))tree[pos] += x;
}
void dfs(int u, int fa) {
S[u].l = ++g;
for(int i = head[u]; ~i; i = edge[i].nx) {
int v = edge[i].to;
if(v == fa)continue;
dfs(v, u);
}
S[u].r = g;
}
int line[maxn + ];
int gx[][maxn];
inline int id(int x) {
return S[x].l;
}
inline void udate(int pos, uLL x) {
fix(id(pos), x);
uLL add = x - w[pos];
w[pos] = x;
for(int i = ; i <= bl[n]; i++) {
Vsum[i] += gx[i][id(pos)] * add;
}
}
inline uLL ask(int l, int r) {
uLL res = ;
if(bl[l] == bl[r]) {
for(int i = l; i <= r; i++) {
res += sum(S[i].r) - sum(S[i].l - );
}
return res;
}
for(int i = l; bl[i] == bl[l]; i++) {
res += sum(S[i].r) - sum(S[i].l - );
}
for(int i = bl[l] + ; i < bl[r]; i++) {
res += Vsum[i];
}
for(int i = (bl[r] - ) * sz + ; i <= r; i++) {
res += sum(S[i].r) - sum(S[i].l - );
}
return res;
}
int main() {
#ifdef local
freopen("in", "r", stdin);
// freopen("w","w",stdout);
#endif
//ios::sync_with_stdio(false);
// cin.tie(0);
init();
scanf("%d%d", &n, &m);
sz = sqrt(n);
for(int i = ; i <= n; ++i)scanf("%d", &w[i]);
for(int i = ; i <= n; ++i) {
bl[i] = (i - ) / sz + ;
}
for(int i = ; i < n; ++i) {
int a, b;
scanf("%d%d", &a, &b);
if(a)add_edge(a, b), add_edge(b, a);
else root = b;
}
dfs(root, -);
for(int i = ; i <= n; ++i)fix(S[i].l, w[i]);
for(int i = ; i <= bl[n]; ++i) {
memset(line, , sizeof line);
for(int j = (i - ) * sz + ; j <= min(i * sz , n); j++) {
line[S[j].l]++, line[S[j].r + ]--;
Vsum[i] += sum(S[j].r) - sum(S[j].l - );
}
int tmp = ;
for(int j = ; j < maxn; j++) {
tmp += line[j];
gx[i][j] = tmp;
}
}
for(int i = ; i < m; i++) {
int d, l, r;
scanf("%d%d%d", &d, &l, &r);
if(d == ) {
udate(l, r);
} else OT(ask(l, r)), putchar('\n');
}
}
-------另外,发现数据的修改权值都是往大修改的,因为里面修改的时候,我传得都是uLL,但ac,懒得改了,看的人注意就可以了。-------
bzoj 4765 普通计算姬(树状数组 + 分块)的更多相关文章
- BZOJ_2141_排队_树状数组+分块
BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...
- gym 100589A queries on the Tree 树状数组 + 分块
题目传送门 题目大意: 给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重. 思路: 思考后发现,以dfs序建立树状数 ...
- 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分
题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...
- BZOJ 4765: 普通计算姬 (分块+树状数组)
传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...
- bzoj 2527 Meteors - 整体二分 - 树状数组
Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby gala ...
- bzoj 4765 普通计算姬 dfs序 + 分块
题目链接 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能 ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- BZOJ 3224 普通平衡树(树状数组)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3224 题意:维护以下操作:(1)插入x:(2)删除x(若有多个相同的数,只删除一个)(3 ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
随机推荐
- PHP童鞋改JAVA代码怎么处理
用线上升级平台代码练手,学习JAVA.飞哥建议我们自己从头再搭建一套,提高会大.我自己作为一个JAVA出身的人,用了几天时间学会PHP的经验来看.最好,先在原来代码基础上改些东西.熟悉了基本语法之后再 ...
- Gym 101257G 24 (概率+二分)
题意: 有一道分值为sa的题,n个人比赛写这道题,按照递减的顺序给出每个人的当前分数,和每个人写不出这道题的概率,让你输出有反超现象出现的期望 思路:由于之前把题目翻译错了导致很久没有相通,后来看了别 ...
- 【Android】XML文件的解析
1.首先我们可以在res包路径下创建一个raw包,然后在raw下创建一个email.xml 文件,并修改其内容如下: <?xml version="1.0" encoding ...
- Angular4.0.0发布总览文章
翻译自angular.io上的关于4.0.0版本发布的文章,内容主要是介绍了4.0.0版本下的改进以及接下来还会有的其他更新,4.0.0其实已经出来好多天了,截止目前都已经到了4.0.1版本了,这也是 ...
- java 基础知识三 java变量
java 基础知识 三 变量 1.作用域 {} 包围起来的代码 称之为代码块,在块中声明的变量只能在块中使用 2.常量 就是固定不变的量,一旦被定义,它的值就不能再被改变. 3.变量 变量必须在程序 ...
- MYSQL 行转列 以及基本的聚合函数count,与group by 以及distinct组合使用
在统计查询中,经常会用到count函数,这里是基础的 MYSQL 行转列 以及基本的聚合函数count,与group by 以及distinct组合使用 -- 创建表 CREATE TABLE `tb ...
- PAT 1057
Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...
- JQuery分页插件封装(源码来自百度,自己封装)
最近由于项目的需要,做了一个基于JQuery的表格分页插件封装,部分源码来源百度,经由自己封装完成. 下面是具体代码和说明,仅供参考.第一步可以先将我的HTML,CSS,JS这三部分的代码创建好后先运 ...
- NSString 为什么要使用copy,而不是retain
NSString 为什么要使用copy,而不是retain1.首先如果使用retain,只是引用计数+1,并没有生成新的对象,所以效率好2.但是使用copy安全.因为NSString 为 NSMuta ...
- storm kafkaSpout 踩坑问题记录! offset问题!
整合kafka和storm例子网上很多,自行查找 问题描述: kafka是之前早就搭建好的,新建的storm集群要消费kafka的主题,由于kafka中已经记录了很多消息,storm消费时从最开始消费 ...