2018 Multi-University Training Contest 2-1007(hdu 6315)-题解
一、题意
给定一个元素个数为$N(1 \le N \le 10^5)$初始序列$a$和$b$,$a$序列的初始值全为$0$,$b$序列的初始值为$1$到$N$的一个排列。有$T(1 \le T \le 10^5)$次操作。操作有如下两种类型:
1、$add\ l\ r$:给序列$a$的区间$[l, r]$内所有元素加$1$;
2、$query\ l\ r$:查询$\sum\limits_{i=l}^{r}\lfloor{\frac{a_i}{b_i}}\rfloor$,并输出。
二、简要思路概括
因为所有操作的总和$tot \le \sum\limits_{i=1}^{N}\frac{T}{i} = T * \sum\limits_{i=1}^{N}\frac{1}{i}$,而可证明调和级数$T * \sum\limits_{i=1}^{N}\frac{1}{i} \le TlogN$。
所以,建立两棵线段树。一棵树$B$维护$b$序列的区间最小值,可支持区间修改。另一棵树$C$维护$\lfloor{\frac{a_i}{b_i}}\rfloor$的区间和。
每次遇到$add$操作时,将$B$线段树的区间$[l, r]$减$1$,时间复杂度$O(logN)$。然后,再对线段树$B$做一遍dfs,如果有叶子节点的值为$0$,则把线段树$C$的对应位置加$1$,同时将该位置的值设置为初始的$b$值。时间复杂度$O(N)$。
所以,单次$add$操作的时间复杂度是$O(N)$,总的时间复杂度是$O(N*T)$。但是,不要觉得会超时。实际的计算量并没有这么大。因为前面已证明,最多只会累加$T \times logN$次。所以,只要代码写得优雅,绝对不会超时。另外,还有一种写法,就是每次对线段树$B$做区间减$1$之后,循环查询$B$线段树的$[l, r]$区间内的最小值,如果最小值为$0$,则把线段树$C$的对应位置加$1$,同时修改该位置的值为初始的$b$值,直到该区间内的最小值不为$0$为止。这样,总的时间复杂度是$O(T*NlogN)$,也不会超时。
三、代码
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 typedef long long ll; struct Node1 { int mv, lazy; }; struct Node2 { int v, sum; }; Node1 b[MAXN * ]; Node2 c[MAXN * ]; int b0[MAXN], N, Q; void push_down(int rt) { if(b[rt].lazy) { , rch = rt << | ; b[lch].mv += b[rt].lazy, b[lch].lazy += b[rt].lazy; b[rch].mv += b[rt].lazy, b[rch].lazy += b[rt].lazy; b[rt].mv = min(b[rt << ].mv, b[rt << | ].mv); b[rt].lazy = ; } } , , int r = N) { if(l >= ul && r <= ur) { if(f)b[rt].mv = val; else b[rt].mv += val, b[rt].lazy += val; return; } push_down(rt); ; , l, mid); | , mid + , r); b[rt].mv = min(b[rt << ].mv, b[rt << | ].mv); } , , int r = N) { if(l == r && l == p) { c[rt].v++, c[rt].sum++; return; } ; , l, mid); | , mid + , r); c[rt].sum = c[rt << ].sum + c[rt << | ].sum; } , , int r = N) { if(ql <= l && qr >= r)return c[rt].sum; , res = ; , l, mid); | , mid + , r); return res; } , , int r = N) { if(l == r) { b[rt].mv = b0[l], update2(l); return; } push_down(rt); ; ].mv == )dfs(ul, ur, rt << , l, mid); | ].mv == )dfs(ul, ur, rt << | , mid + , r); b[rt].mv = min(b[rt << ].mv, b[rt << | ].mv); } int main() { // freopen("input.txt", "r", stdin); ]; int l, r; while(~scanf("%d%d", &N, &Q)) { , tt = N << ; i < tt; ++i)b[i].mv = INT_MAX, b[i].lazy = ; memset(c, , sizeof(c)); ; i <= N; ++i)scanf(); while(Q--) { scanf("%s%d%d", cmd, &l, &r); ] == 'a') { update1(l, r, -, ); dfs(l, r); } else cout << query2(l, r) << endl; } } ; }
2018 Multi-University Training Contest 2-1007(hdu 6315)-题解的更多相关文章
- hdu 4941 2014 Multi-University Training Contest 7 1007
Magical Forest Time Limit: 24000/12000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- 2017 Multi-University Training Contest - Team 2 &&hdu 6050 Funny Function
Funny Function Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 2017 Multi-University Training Contest - Team 2 &&hdu 6053 TrickGCD
TrickGCD Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- 2017 Multi-University Training Contest - Team 2&&hdu 6047 Maximum Sequence
Maximum Sequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 6315 Naive Operations (2018 Multi-University Training Contest 2 1007)
Naive Operations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 502768/502768 K (Java/Other ...
- HDU 6356.Glad You Came-线段树(区间更新+剪枝) (2018 Multi-University Training Contest 5 1007)
6356.Glad You Came 题意就是给你一个随机生成函数,然后从随机函数里确定查询的左右区间以及要更新的val值.然后最后求一下异或和就可以了. 线段树,区间最大值和最小值维护一下,因为数据 ...
- HDU 6315.Naive Operations-线段树(两棵树合并)(区间单点更新、区间最值、区间求和)+思维 (2018 Multi-University Training Contest 2 1007)
6315.Naive Operations 题意很好理解,但是因为区间求和求的是向下取整的a[i]/b[i],所以直接分数更新区间是不对的,所以反过来直接当a[i]==b[i]的时候,线段树对应的位置 ...
- 【2018 Multi-University Training Contest 2 1007】Naive Operations
[链接] 我是链接,点我呀:) [题意] 给你两个数组a,b; b数组是1..n的一个排列. 现在给你两种操作: add l,r将a[l..r]都加上1 query l,r 询问$∑^r_l\frac ...
- 2018 Nowcoder Multi-University Training Contest 2
目录 Contest Info Solutions A. run D. monrey G. transform H. travel I. car J. farm Contest Info Practi ...
随机推荐
- HDU 1556 Color the ball(线段树:区间更新)
http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和 ...
- c++ 反转容器的元素顺序(reverse)
#include <vector> #include <iostream> #include <iterator> #include <algorithm&g ...
- Django框架基于session的登录/注销实现
博主最近想基于Django框架开发一个测试平台,第一版先实现查看下载自动化的测试报告文件 第一步:前端框架 网上选择一款开源boostrap的前端框架 AdminLTE,这里给个链接 https:/ ...
- Java中处理异常的9个最佳实践
Java中的异常处理不是一个简单的话题.初学者很难理解,甚至有经验的开发人员也会花几个小时来讨论应该如何抛出或处理这些异常. 这就是为什么大多数开发团队都有自己的异常处理的规则和方法.如果你是一个团队 ...
- js将 HTML 页面生成 PDF 并下载
最近碰到个需求,需要把当前页面生成 pdf,并下载.弄了几天,自己整理整理,记录下来,我觉得应该会有人需要 :) 先来科普两个插件: html2Canvas 简介 我们可以直接在浏览器端使用html2 ...
- 个人知识管理系统Version1.0开发记录(09)
MyBatis初试 MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索. 运用Mybatis框 ...
- 【Python】operator 模块简单介绍
简单介绍几个常用的函数,其他的请参考文档. operator.concat(a, b) **operator.__concat__(a, b)** 对于 a.b序列,返回 a + b(列表合并) -- ...
- 转载 ORACLE中实现表变量的方法
源文地址:http://blog.itpub.net/750077/viewspace-2134222/ 经常看到SQLSERVER 中用表变量类型的方式就能做到缓存一个比较大的中间结果, 然后再对这 ...
- ES6介绍二 函数的增强
ES6对于函数的使用新增了很多实用的API,JS的函数跟很多后台语言PHP,ASP.NET开始看齐: 1. 参数默认值: 以前我们为了给函数创建默认值,必须用一种冗杂的语句,而且有歧义的语句. //E ...
- 历史上的重大软件BUG启示录第9篇---微软的硬件尝试
(图片来源于网络) 2001年苹果公司发布第一代iPod,它的推出在当时引起了轰动,它拥有大容量存储空间和全新的操作方式,并且还非常漂亮(在当时看来),因此在市场上大受欢迎,苹果公司也因此赚的盆满钵满 ...