HDU 6315 Naive Operations 【势能线段树】
<题目链接>
题目大意:
给出两个序列,a序列全部初始化为0,b序列为输入值。然后有两种操作,add x y就是把a数组[x,y]区间内全部+1,query x y是查询[x,y]区间内∑[ai/bi]。([ai/bi]代表ai/bi后向下取整)
解题分析:
首先,如果每次+1都暴力更新到每个叶子节点肯定会超时,但是如果不更新到叶子节点又不好维护每个节点对应区间 ∑[ai/bi] 的值,所以我们可以每个节点都维护四个值。sum值代表这个区间每个节点整数部分的所有数之和,lazy进行懒惰标记,避免每次更新到叶子节点,mxa记录该区间内分子的最大值,mnb记录该区间内分母的最小值。之所以要维护这两个最大最小值是因为,当进行区间整体+1操作的时候,如果该区间内最大的分子都小于分母时,说明这个区间在进行+1操作后,并没有对该区间的sum值做出贡献,所以此时就可以将这个+1操作lazy到这个节点;但是如果对区间整体+1后,最大分子大于等于最小分母,此时,就需要继续向下更新,直到找到那个(或者几个)分子大于等于分母的根节点,然后将该节点的sum+1,同时将b值加上原始的brr[l]值(其实我不太明白这一步为什么要这么做,我觉的这步等效于该点的mxa值-该点的mnb值啊,然而这样改了以后超时 T_T)。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define Lson rt<<1,l,mid
#define Rson rt<<1|1,mid+1,r
const int M =1e5+; int n,m;
struct Tree{
int lazy,sum;
int mxa,mnb;
}tr[M<<];
int brr[M]; void Pushdown(int rt){
if(tr[rt].lazy){
int tmp=tr[rt].lazy;
tr[rt<<].lazy+=tmp,tr[rt<<|].lazy+=tmp;
tr[rt<<].mxa+=tmp,tr[rt<<|].mxa+=tmp;
tr[rt].lazy=;
}
}
void Pushup(int rt){
tr[rt].sum=tr[rt<<].sum+tr[rt<<|].sum;
tr[rt].mxa=max(tr[rt<<].mxa,tr[rt<<|].mxa); //维护该区间内分子的最大值和分母的最小值
tr[rt].mnb=min(tr[rt<<].mnb,tr[rt<<|].mnb);
}
void build(int rt,int l,int r){ //初始化
tr[rt].lazy=;
if(l==r){
tr[rt].mxa=tr[rt].sum=;
tr[rt].mnb=brr[l];
return;
}
int mid=(l+r)>>;
build(Lson);
build(Rson);
Pushup(rt);
}
void update(int rt,int l,int r,int L,int R){ //这个函数是本题的关键
if(L<=l&&r<=R){
tr[rt].mxa++;
if(tr[rt].mxa<tr[rt].mnb){ //如果最大的分子小于最大的分母,说明这个区间内的所有叶子在分子+1之后,没有对sum值多做出贡献,所以我们先将这个操作lazy在这个节点
tr[rt].lazy++;
return;
}
if(l==r&&tr[rt].mxa>=tr[rt].mnb){ //如果向下找到了那个分子大于等于分母的叶子节点,那么该节点贡献+1,且将分母加上最初始的防御值,相当于将该真分数的整数部分提出后,再将其变成假分数,方便以后继续统计贡献
tr[rt].sum++;
tr[rt].mnb+=brr[l]; //我觉的这一步应该等效于tr[rt].mxa-=tr[rt].mnb啊,然而这样改了以后超时
return;
}
}
Pushdown(rt);
int mid=(l+r)>>;
if(L<=mid)update(Lson,L,R);
if(R>mid)update(Rson,L,R);
Pushup(rt);
}
int query(int rt,int l,int r,int L,int R){ //查询该区间内所有数的整数部分之和
if(L<=l&&r<=R)return tr[rt].sum;
Pushdown(rt);
int ans=;
int mid=(l+r)>>;
if(L<=mid)ans+=query(Lson,L,R);
if(R>mid)ans+=query(Rson,L,R);
return ans;
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=;i<=n;i++)
scanf("%d",&brr[i]);
build(,,n);
char op[];
while(m--){
int x,y;
scanf("%s%d%d",&op,&x,&y);
if(op[]=='a')update(,,n,x,y);
else printf("%d\n",query(,,n,x,y));
}
}
return ;
}
2018-10-15
HDU 6315 Naive Operations 【势能线段树】的更多相关文章
- HDU 6315 Naive Operations(线段树+区间维护)多校题解
题意:a数组初始全为0,b数组题目给你,有两种操作: 思路:dls的思路很妙啊,我们可以将a初始化为b,加一操作改为减一,然后我们维护一个最小值,一旦最小值为0,说明至少有一个ai > bi,那 ...
- HDU 6351 Naive Operations(线段树)
题目: http://acm.hdu.edu.cn/showproblem.php?pid=6315 Naive Operations Time Limit: 6000/3000 MS (Java/O ...
- 杭电多校第二场 hdu 6315 Naive Operations 线段树变形
Naive Operations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 502768/502768 K (Java/Other ...
- HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树
hdu 6315 题意:对于一个数列a,初始为0,每个a[ i ]对应一个b[i],只有在这个数字上加了b[i]次后,a[i]才会+1. 有q次操作,一种是个区间加1,一种是查询a的区间和. 思路:线 ...
- HDU 6315 Naive Operations(线段树区间整除区间)
Problem DescriptionIn a galaxy far, far away, there are two integer sequence a and b of length n.b i ...
- HDU - 6315 Naive Operations (线段树+思维) 2018 Multi-University Training Contest 2
题意:数量为N的序列a和b,a初始全为0,b为给定的1-N的排列.有两种操作:1.将a序列区间[L,R]中的数全部+1:2.查询区间[L,R]中的 ∑⌊ai/bi⌋(向下取整) 分析:对于一个位置i, ...
- HDU 6315 Naive Operations(线段树+复杂度均摊)
发现每次区间加只能加1,最多全局加\(n\)次,这样的话,最后的答案是调和级数为\(nlogn\),我们每当答案加1的时候就单点加,最多加\(nlogn\)次,复杂度可以得当保证. 然后问题就是怎么判 ...
- 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 6315: Naive Operations
Naive Operations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 502768/502768 K (Java/Other ...
- HDU-6315:Naive Operations(线段树+思维)
链接:HDU-6315:Naive Operations 题意: In a galaxy far, far away, there are two integer sequence a and b o ...
随机推荐
- 将两个列表合并为字典_其中一个列表为Key_一个列表为Value
#定义两个列表 list1 = range(0,10) list2 = range(10,20) #合并为字典,调用dict(zip()) dict_name = dict(zip(list1,lis ...
- 1146. Topological Order (25)
This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topol ...
- SQL中exists和in的区别
- ubuntu + JetSonNano+OpenCV3.4.8
首先强调一点,如果要配置darknet环境,不建议安装该版本!!! 安装opencv前,建议先检测自己的系统是否已经装过其他版本, 检查方式: (1)查看是否安装opencv库: pkg-config ...
- php怎么获取js的变量值
使用php做网站的时候,经常需要我们与前端的页面进行交互,有时候我们还需要通过php来获得js变量中的值,这种情况我们可以通过在其中嵌入js代码的方式来获得这个变量. 首先我们创建一个test的php ...
- BZOJ 4836: [Lydsy1704月赛]二元运算 分治FFT
Code: #include<bits/stdc++.h> #define ll long long #define maxn 500000 #define setIO(s) freope ...
- SQL中MINUS的用法与UNION的用法
一:MINUS指令 其是运用在两个 SQL 语句上.它先找出第一个 SQL 语句所产生的结果,然后看这些结果有没有在第二个 SQL语句的结果中.如果有的话,那第一个SQL结果数据就被去除,而不会在最后 ...
- vu项目中按F5刷新element菜单没有根据路由匹配菜单解决办法
element组件的菜单中设置:default-active,这个是选择哪个菜单的 然后在created里边增加 因为每次刷新都是要经过这个的.注意data里边也要同步.
- css中div垂直居中的方法。
利用绝对定位实现的居中 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- jQuery中的serializer序列化—炒鸡好用
jQuery.serializer()序列化 serialize()函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串. serialize()函数常用于将表单内容序列化,以便用于AJAX提 ...