<题目链接>

题目大意:

给出两个序列,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 【势能线段树】的更多相关文章

  1. HDU 6315 Naive Operations(线段树+区间维护)多校题解

    题意:a数组初始全为0,b数组题目给你,有两种操作: 思路:dls的思路很妙啊,我们可以将a初始化为b,加一操作改为减一,然后我们维护一个最小值,一旦最小值为0,说明至少有一个ai > bi,那 ...

  2. HDU 6351 Naive Operations(线段树)

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=6315 Naive Operations Time Limit: 6000/3000 MS (Java/O ...

  3. 杭电多校第二场 hdu 6315 Naive Operations 线段树变形

    Naive Operations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Other ...

  4. HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树

    hdu 6315 题意:对于一个数列a,初始为0,每个a[ i ]对应一个b[i],只有在这个数字上加了b[i]次后,a[i]才会+1. 有q次操作,一种是个区间加1,一种是查询a的区间和. 思路:线 ...

  5. HDU 6315 Naive Operations(线段树区间整除区间)

    Problem DescriptionIn a galaxy far, far away, there are two integer sequence a and b of length n.b i ...

  6. 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, ...

  7. HDU 6315 Naive Operations(线段树+复杂度均摊)

    发现每次区间加只能加1,最多全局加\(n\)次,这样的话,最后的答案是调和级数为\(nlogn\),我们每当答案加1的时候就单点加,最多加\(nlogn\)次,复杂度可以得当保证. 然后问题就是怎么判 ...

  8. 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 ...

  9. HDU 6315: Naive Operations

    Naive Operations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Other ...

  10. HDU-6315:Naive Operations(线段树+思维)

    链接:HDU-6315:Naive Operations 题意: In a galaxy far, far away, there are two integer sequence a and b o ...

随机推荐

  1. Node.JS-经典教程

    目录 1. 下载地址 2. 目录 1. 下载地址 https://www.cnblogs.com/coco56/p/11223189.html 在视频教程那里 2. 目录 00课件.rar 01.历史 ...

  2. fastjson合并json数组中相同的某个元素

    /** * @param array JSON数组 * @param array 需合并后的某个元素名 */ private static JSONArray mgreArray(JSONArray ...

  3. 设置div 居中 和得到dom元素高度

    javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...

  4. Delphi GridPanel Percent百分比设置

    可能很多人都有这个困扰,为什么每次设置一个百分比后,值都会改变,只有设置成absolute​才会正常,经摸索发现,是因为精度引起,设置percent的时候,需要将精确到多个小数位.如要有3列,需要设置 ...

  5. php strcspn()函数 语法

    php strcspn()函数 语法 作用:输出在字符串中找到某字符之前查找的字符数.直线电机参数 语法:strcspn(string,char,start,length) 参数: 参数 描述 str ...

  6. 观察者模式使用WebForm实现的例子

    观察者模式是一种可以描述一对多对象依赖关系的行为模式.当一个对象状态发生变化时,依赖它的其它对象会自动被更新状态.下面这个图展示了观察者模式的层级: 举个例子吧,我们某个报表界面现在有个dashboa ...

  7. [CSP-S模拟测试]:太阳神(莫比乌斯反演)

    题目描述 太阳神拉很喜欢最小公倍数,有一天他想到了一个关于最小公倍数的题目.求满足如下条件的数对$(a,b)$对数:$a,b$均为正整数且$a,b\leqslant n$而$lcm(a,b)>n ...

  8. Linux(RHEL7)下安装vsftp服务

    1.安装vsftp(没有配置yum源的先配置yum源) yum install -y vsftpd 2.启动ftp服务 systemctl start vsftpd.service 3.打开防火墙 f ...

  9. Flask 重定向到动态url

    url_for() 函数是动态构建一个网址给特定的功能是非常有用的.该函数接受函数的名称作为第一个参数,并接受一个或多个关键字参数,每个参数对应于URL的变量部分. 以下脚本演示了使用 url_for ...

  10. 测开之路六十四:UI测试平台之前端页面

    {% extends "base.html" %} {% block script %} <!-- 引入js文件,需要在base.html留入口,不然渲染会出问题. --&g ...