老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有log(n)次)

于是暴力啊暴力,结果我归天了。

好吧,在各种题解的摧残下,我终于出了一篇巨好看(chou lou)代码(很多结构体党嫌丑)



那么具体除法怎么实现就是关键了

对于单个点或者区间内的数完全相同的区间,可以做成区间减法

因为除法会使数变小,而相同的数减小的量是相同的,

那么怎么判断区间内的数是否完全相同呢?

可以维护一个区间最小与区间最大,如果一个区间内最小数等于最大数,那么显然这个区间内所有数相等

区间最小与区间最大就不用说了吧?

然后暴力一波

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll sum[400101]={0}, minn[400101],maxx[400001]={0},add[400101]={0},a[401001];
int n,m;
void pushup(ll rt){
sum[rt]=sum[rt<<1|1]+sum[rt<<1];
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
inline ll Div(ll x, ll y) {//从样例分析出这道题是向下取整的除法
return floor((double)x/y);
}
void build(ll l,ll r,ll rt){
if(l==r){
sum[rt]=a[l];
minn[rt]=a[l];
maxx[rt]=a[l];
return ;
}
long long mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void pushdown(ll rt,ll ln,ll rn){
if(add[rt]!=0){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
minn[rt<<1]+=add[rt];
minn[rt<<1|1]+=add[rt];
maxx[rt<<1]+=add[rt];
maxx[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void update1(ll l,ll r,ll c,ll L,ll R,ll rt){
if(l>=L&&r<=R){
sum[rt]+=c*(r-l+1);
add[rt]+=c;minn[rt]+=c;maxx[rt]+=c;
return ;
}
ll mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);
if(L<=mid)update1(l,mid,c,L,R,rt<<1);
if(R>mid)update1(mid+1,r,c,L,R,rt<<1|1);
pushup(rt);
}
void update2(ll l,ll r,ll c,ll L,ll R,ll rt){//对于除法的暴力操作
if (l >=L&&r<=R&&maxx[rt]-Div(maxx[rt],c)==minn[rt]-Div(minn[rt],c)){
ll D=Div(maxx[rt],c)-maxx[rt];
add[rt]+=D;maxx[rt]+=D;minn[rt]+=D;
sum[rt]+=D*(r-l+1);
return;
}
ll mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);
if(L<=mid)update2(l,mid,c,L,R,rt<<1);
if(mid<R)update2(mid+1,r,c,L,R,rt<<1|1);
pushup(rt);
}
ll query1(ll l,ll r,ll L,ll R,ll rt){
if(l>=L&&r<=R){
return sum[rt];
}
ll mid=(l+r)>>1;
ll ans=0;
pushdown(rt,mid-l+1,r-mid);
if(L<=mid)ans+=query1(l,mid,L,R,rt<<1);
if(R>mid)ans+=query1(mid+1,r,L,R,rt<<1|1);
return ans;
}
ll query2(ll l,ll r,ll L,ll R,ll rt){
if(l>=L&&r<=R){
return minn[rt];
}
ll mid=(l+r)>>1;
ll ans=1e18;
pushdown(rt,mid-l+1,r-mid);
if(L<=mid)ans=min(ans,query2(l,mid,L,R,rt<<1));
if(R>mid)ans=min(ans,query2(mid+1,r,L,R,rt<<1|1));
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%lld",&a[i]);
//memset(flag,1,sizeof(flag));
build(0,n-1,1);
while(m--){
long long c,x,y,k;
scanf("%lld%lld%lld",&c,&x,&y);
if(c==1){scanf("%lld",&k);update1(0,n-1,k,x,y,1);}
if(c==2){scanf("%lld",&k);update2(0,n-1,k,x,y,1);}
if(c==4)printf("%lld\n",query1(0,n-1,x,y,1));
if(c==3)printf("%lld\n",query2(0,n-1,x,y,1));
}
return 0;
}

「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)的更多相关文章

  1. LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法

    题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...

  2. loj#6029. 「雅礼集训 2017 Day1」市场(线段树)

    题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...

  3. 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析

    题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...

  4. #6029. 「雅礼集训 2017 Day1」市场 [线段树]

    考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...

  5. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

  6. 【loj6029】「雅礼集训 2017 Day1」市场&&【uoj#228】基础数据结构练习题

    题解: 这两道题加上区间取min max应该算线段树几道比较不寻常的题目 其实也是挺好理解的 对于区间/d 显然在log次后就会等于0 而我们注意到如果区间中数都相等那么就可以一起除 也就是说每个区间 ...

  7. loj6029 「雅礼集训 2017 Day1」市场

    传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区 ...

  8. 【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)

    点此看题面 大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和. 线段树维护区间除法 区间加法.区间求\(min\)和区间求和都是线段树基本操作,因此略过不提. ...

  9. 【loj6029】「雅礼集训 2017 Day1」市场

    题目 题意:四种操作,区间加法.区间除法(下取整).区间求最小值.区间求和. 第1.3.4个操作都是摆设,关键在于如何做区间除法. 很明显不能直接把区间的和做除法后向下取整,因为区间和可能会多凑出一个 ...

随机推荐

  1. 基于多用户的Oracle数据泵导入导出数据

    登陆SqlPlus: SqlPlus sys/syspwd@MyOrcl AS sysdba 其中:syspwd:sys的登陆密码:MyOrcl:所创建的数据库服务名. 创建数据泵: create o ...

  2. 09 OCP知识点讲解 之 LRU链与脏LRU链

    OCP知识点讲解 之 LRU链与脏LRU链 分类: Oracle 2012-06-30 10:49:26   一.LRU链: 任何缓存的大小都是有限制的,并且总不如被缓存的数据多.就像Buffer c ...

  3. 产品 | What's产品经理

    如果想知道什么是产品,首先需要知道什么是缔造者.其名曰:"产品经理". PS:产品经理一词在国内大多时候泛指"互联网产品经理". 对于产品经理这一职位,说实在很 ...

  4. iOS7下Status Bar字体颜色修改

    原文来自这里:iOS7下Status Bar字体颜色修改. 旧项目在iOS7上遇到status bar字体颜色需要修改的问题,症状如下:导航栏设置为黑色后,iphone上status bar的字体颜色 ...

  5. C++分享笔记:扑克牌的洗牌发牌游戏设计

    笔者在大学二年级期间,做过的一次C++程序设计:扑克牌的洗牌发牌游戏.具体内容是:除去大王和小王,将52张扑克牌洗牌,并发出5张牌.然后判断这5张牌中有几张相同大小的牌,是否是一条链,有几个同花等. ...

  6. 获取DOM

    <template> <div> <header-vue :msg="msg" ref="header">heheh< ...

  7. tomcat安装、配置相关的几个点

    Connector port="8080"HTTP协议的默认端口号:8080 FTP协议的默认端口号:21 1.tomcat的安装目录要与Java jre的安装目录一致. bin: ...

  8. fake_useragent 封装好user-agent的模块

    from fake_useragent import UserAgent useragent = UserAgent()print(useragent.random)

  9. 常量的三种定义方式和static在c语言中的三种修饰

    c语言的常量在执行期间为固定值,在定义后无法被修改常量可以是任何的数据基本类型,可以为整形,浮点常量,字符和字符串常量1,使用const关键字2, 使用宏定义3,使用枚举常量 枚举: #include ...

  10. C++ STL lower_bound()和upper_bound()

    lower_bound()和upper_bound()用法 1.在数组上的用法 假设a是一个递增数组,n是数组长度,则 lower_bound(a, a+n, x):返回数组a[0]~a[n-1]中, ...