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 ...
随机推荐
- UVa 10534 波浪子序列(快速求LIS)
https://vjudge.net/problem/UVA-10534 题意:给定一个长度为n的整数序列,求一个最长子序列(不一定连续),使得该序列的长度为2k+1,前k+1个数严格递增,后k+1个 ...
- PrestaShop 1.7 用户付款的时候无法支付错误
用户付款的时候出现错误,错误的信息是没有支付方式. 这个有可能是你后台支付的国家限制没有选择. 请确定你已经选择了支付国家限制已经选择了. 当选择成功后,你应该可以看到下面的选择项.
- facebook开源的prophet时间序列预测工具---识别多种周期性、趋势性(线性,logistic)、节假日效应,以及部分异常值
简单使用 代码如下 这是官网的quickstart的内容,csv文件也可以下到,这个入门以后后面调试加入其它参数就很简单了. import pandas as pd import numpy as n ...
- 什么是API?我们常说调用API
如果你不知道 API 是什么,说明你英语真的很差. API 就是 Application Programming Interface 三个单词,如果你不能顾名思义的话,我就举例说明. 1. DOM A ...
- cvs的规范以及介绍(转)
原文链接:http://blog.csdn.net/zlzlei/article/details/9236403 1. CSV的全称是叫Comma Separated Value 2. CSV的MIM ...
- Alpha冲刺(11/10)
拖鞋旅游队团队事后诸葛亮会议 前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10054510.html 时间:2018-12-1 20:00 地 ...
- C++17中那些值得关注的特性(上)
C++17标准在2017上半年已经讨论确定,正在形成ISO标准文档,今年晚些时候会正式发布.本文将介绍最新标准中值得开发者关注的新特新和基本用法. 总的来说C++17相比C++11的新特性来说新特性不 ...
- Servlet不是线程安全的。
要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的. 当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个 ...
- Ubuntu用户管理
本文主要介绍Ubuntu的用户管理,包括建立和删除用户,用户授权等 ================== 创建用户并授权================== sudo adduser xxx 会在ho ...
- git 解决冲突问题
问题描述: 一般来说,只要多人提交同一仓库,必然会有冲突的发生. Git解决 利用git解决冲突很简单,最常规的方法莫过于工作之前先更新整个project,完成之后及时提交.然而尽管这样做,也难免有人 ...