【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)
大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和。
线段树维护区间除法
区间加法、区间求\(min\)和区间求和都是线段树基本操作,因此略过不提。
此题关键在于维护区间除法。
而这有一个复杂度玄学的做法,即将区间除法转化为区间减法。
可以考虑对于每个区间,记录下其最小值和最大值,若最小值和最大值做区间除法所需减去的数相等,则易证整个区间所需减去的数相等。
则我们可以将区间\([l,r]\)分成若干个区间,直至区间最小值与最大值相等即可。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define RL Reg LL
#define Con const
#define CI Con int&
#define CL Con LL&
#define I inline
#define W while
#define N 100000
#define INF 1e9
#define LL long long
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int f,T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0,f=1;W(!D) f=c^'-'?1:-1;W(x=tn+(c&15),D);x*=f;}
Tp I void write(Ty x) {x<0&&(pc('-'),x=-x);W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
#undef D
}F;
class SegmentTree//线段树
{
private:
#define STO l,mid,rt<<1
#define ORZ mid+1,r,rt<<1|1
#define PU(x) (O[x]=O[x<<1]+O[x<<1|1])//上传信息
#define PD(x) (O[x].A&&(O[x<<1]+=O[x].A,O[x<<1|1]+=O[x].A,O[x].A=0))//下传标记
#define GV(x,v) (x<0?x-(x+1)/v+1:x-x/v)//求出x在除v之后减去的数
static Con int SZ=N;int n,v[N+5];
struct Interval//存储区间信息
{
int L,Mn,Mx,A;LL S;I Interval(CI l=0,CL s=0,CI mn=INF,CI mx=-INF,CI a=0):L(l),S(s),Mn(mn),Mx(mx),A(a){}//构造函数
I Interval operator + (Con Interval& t) Con {return Interval(L+t.L,S+t.S,min(Mn,t.Mn),max(Mx,t.Mx));}//合并区间信息
I void operator += (CI x) {S+=L*x,Mn+=x,Mx+=x,A+=x;}I void operator /= (CI x) {RI t=GV(Mn,x);*this+=-t;}//更新区间信息
}O[N<<2];
I void bld(CI l,CI r,CI rt)//建树
{
if(!(l^r)) return (void)(O[rt]=Interval(1,v[l],v[l],v[l]));
RI mid=l+r>>1;bld(STO),bld(ORZ),PU(rt);
}
I void upt1(CI l,CI r,CI rt,CI ul,CI ur,CI v)//区间加法
{
if(ul<=l&&r<=ur) return O[rt]+=v;RI mid=l+r>>1;PD(rt);
ul<=mid&&(upt1(STO,ul,ur,v),0),ur>mid&&(upt1(ORZ,ul,ur,v),0),PU(rt);
}
I void upt2(CI l,CI r,CI rt,CI ul,CI ur,CI v)//区间除法
{
if(ul<=l&&r<=ur&&GV(O[rt].Mn,v)==GV(O[rt].Mx,v)) return O[rt]/=v;RI mid=l+r>>1;PD(rt);
ul<=mid&&(upt2(STO,ul,ur,v),0),ur>mid&&(upt2(ORZ,ul,ur,v),0),PU(rt);
}
I LL qry1(CI l,CI r,CI rt,CI ql,CI qr)//区间求Min
{
if(ql<=l&&r<=qr) return O[rt].Mn;RI mid=l+r>>1;RL t=INF;PD(rt);
return ql<=mid&&(p=qry1(STO,ql,qr),Gmin(t,p)),qr>mid&&(p=qry1(ORZ,ql,qr),Gmin(t,p)),t;
}
I LL qry2(CI l,CI r,CI rt,CI ql,CI qr)//区间求和
{
if(ql<=l&&r<=qr) return O[rt].S;RI mid=l+r>>1;RL t=0;PD(rt);
return ql<=mid&&(t+=qry2(STO,ql,qr)),qr>mid&&(t+=qry2(ORZ,ql,qr)),t;
}
public:
I void Init(CI len,int* s) {for(RI i=1;i<=len;++i) v[i]=s[i];bld(1,n=len,1);}
I void Add(CI l,CI r,CI v) {upt1(1,n,1,l,r,v);}I void Div(CI l,CI r,CI v) {upt2(1,n,1,l,r,v);}
I int QMin(CI l,CI r) {return qry1(1,n,1,l,r);}I LL QSum(CI l,CI r) {return qry2(1,n,1,l,r);}
}S;
int main()
{
RI Qtot,i,op,x,y,v;for(F.read(n,Qtot),i=1;i<=n;++i) F.read(a[i]);
S.Init(n,a);W(Qtot--)
{
switch(F.read(op,x,y),++x,++y,op)
{
case 1:F.read(v),S.Add(x,y,v);break;case 2:F.read(v),S.Div(x,y,v);break;
case 3:F.writeln(S.QMin(x,y));break;case 4:F.writeln(S.QSum(x,y));break;
}
}return F.clear(),0;
}
【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)的更多相关文章
- 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析
题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...
- 「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)
老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有log(n)次) 于是暴力啊暴力,结果我归天了. 好吧,在各种题解的摧残下,我终于出了一篇巨好看(chou lou)代码(很多结构体党 ...
- #6029. 「雅礼集训 2017 Day1」市场 [线段树]
考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...
- LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法
题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...
- loj6029 「雅礼集训 2017 Day1」市场
传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区 ...
- LOJ6029「雅礼集训 2017 Day1」市场 (线段树)
题面 从前有一个学校,在 O n e I n D a r k \rm OneInDark OneInDark 到任之前风气都是非常良好的,自从他来了之后,发布了一系列奇怪的要求,挟制了整个学校,导致风 ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
- 【loj6029】「雅礼集训 2017 Day1」市场&&【uoj#228】基础数据结构练习题
题解: 这两道题加上区间取min max应该算线段树几道比较不寻常的题目 其实也是挺好理解的 对于区间/d 显然在log次后就会等于0 而我们注意到如果区间中数都相等那么就可以一起除 也就是说每个区间 ...
随机推荐
- xshell传输文件到linux
我们使用xshell来连接linux之后会发现方便了很多~然而使用xshell要怎么把本地文件传到linux上面呢? 1.yum安装一款工具.#yum install lrzsz -y 2检查是否安 ...
- python3 unittest数据驱动
我们在自动化测试的时候,有没有遇到这样的问题?例如一个登录的接口要做自动化,会有很多case(用例),密码错误,密码正确这种.在继承unittest.TestCase的类中,凡是以“test”开头的方 ...
- js模仿微信语音播放的小功能
自己写的一个模仿微信语音播放的小功能,实现的主要功能是:点击播放,点击暂停,播放切换,,, 代码如下: <!DOCTYPE html> <html lang="en&qu ...
- java生成复杂word文档
在Web应用中,有时需要按照固定的模板将数据导出到Word,如流程审批单,在流程处理完成后将处理过程按照流程单的要求导出,有时程序中需要实现生成 标准Word文档,要求能够打印,并且保持页面样式不变, ...
- js监听dom元素内容变化
$("#divid").bind('DOMNodeInserted', function(e) { alert('element now contains: ' + $(e.tar ...
- Naive Operations
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6315 学习博客:https://blog.csdn.net/SunMoonVocano/article ...
- 为什么我用gets不行呢?系统无视了我的存在!!!
梗概:为什么我用gets不行呢?系统无视了我的存在!!!我还没输入东东啊..怎么就提示[请安任意键继续]的?? 原来是缓冲区的问题啊? 一.什么是缓冲区 缓冲区又称为缓存,它是内存空间的一部分.也就是 ...
- git使用笔记-提高篇
一.分支.合并 1.合并一个特定提交 a specific commit git cherry-pick commit-id 把commit-id代表的本次提交合并到当前分支,如果有冲突需要解决后,提 ...
- Murano Application
OpenStack Application Link: http://apps.openstack.org/ Those applications include Murano packages, H ...
- PyCharm5 破解汉化
作者博文地址:https://www.cnblogs.com/liu-shuai/ 破解: 将下列序列号复制到软件激活界面即可破解. 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0 ...