link

试题分析

可以容易发现此题维护的是一个数据结构,支持区间加,区间除,区间查询最大值。其实就是在$\log$级复杂度内维护除法操作。

我们发现当除数很大或者此串序列大小差不多时,我们令$a_i$为原来,$b_i$为现在,则对于$[l,r]$中的任意一个数$i$,则出现$a_i-b_i$为恒值。则我们可以用线段树去维护即可。

举个例子:

当我们要在$1,2,3,4,5$中每一个数除以$1$时,我们可以发现每个数都$a_i-b_i=0$,所以做区间减法即可

当我们要在$2,3,3,3,3$中每一个数除以$2$时,$a_i-b_i=2$.所以此段区间每个数减$2$即可。

那我们则么快速寻找是否会一样,我们只要看一下当前序列最大值与最小值的变化即可,因为他们是具有代表性的。

然后就只要维护一个区间修改,最大值,最小值,区间查询的线段树即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<climits>
#define int long long
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
const int N=;
int n,q;
int val[N],maxn[N<<],minn[N<<],sum[N<<],tag[N<<];
void pushup(int k){
maxn[k]=max(maxn[k<<],maxn[k<<|]);
minn[k]=min(minn[k<<],minn[k<<|]);
sum[k]=sum[k<<]+sum[k<<|];
}
void build(int k,int l,int r){
if(l==r){maxn[k]=minn[k]=sum[k]=val[l];return;}
int mid=l+r>>;
build(k<<,l,mid),build(k<<|,mid+,r);
pushup(k);
return;
}
void pushdown(int k,int l,int r){
if(tag[k]==) return;
int mid=l+r>>;
sum[k<<]+=(mid-l+)*tag[k],sum[k<<|]+=(r-mid)*tag[k];
maxn[k<<]+=tag[k],minn[k<<]+=tag[k];
maxn[k<<|]+=tag[k],minn[k<<|]+=tag[k];
tag[k<<]+=tag[k],tag[k<<|]+=tag[k];
tag[k]=;
return;
}
void add(int k,int l,int r,int x,int y,int w){
// cout<<"l:"<<l<<" r:"<<r<<" w:"<<w<<endl;
if(x<=l&&r<=y){
maxn[k]+=w,minn[k]+=w,tag[k]+=w;sum[k]+=(r-l+)*w;
return;
}
pushdown(k,l,r);
int mid=l+r>>;
if(x<=mid) add(k<<,l,mid,x,y,w);
if(mid<y) add(k<<|,mid+,r,x,y,w);
pushup(k);
return;
}
void div(int k,int l,int r,int x,int y,int w){
if(x<=l&&r<=y){
int s1=maxn[k]-(int)floor((double)maxn[k]/(double)w),s2=minn[k]-(int)floor((double)minn[k]/(double)w);
if(s1==s2){
tag[k]-=s1;sum[k]-=(r-l+)*s1;maxn[k]-=s1,minn[k]-=s1;
return;
}
}
pushdown(k,l,r);
int mid=l+r>>;
if(x<=mid) div(k<<,l,mid,x,y,w);
if(mid<y) div(k<<|,mid+,r,x,y,w);
pushup(k);
return;
}
int query_minn(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return minn[k];
int res=LLONG_MAX,mid=l+r>>;
pushdown(k,l,r);
if(x<=mid) res=min(res,query_minn(k<<,l,mid,x,y));
if(mid<y) res=min(res,query_minn(k<<|,mid+,r,x,y));
pushup(k);
return res;
}
int query_sum(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return sum[k];
pushdown(k,l,r);
int res=,mid=l+r>>;
if(x<=mid) res+=query_sum(k<<,l,mid,x,y);
if(mid<y) res+=query_sum(k<<|,mid+,r,x,y);
pushup(k);
return res;
}
void find1(int k,int l,int r){
if(l==r){cout<<maxn[k]<<" ";return;}
int mid=l+r>>;
pushdown(k,l,r);
find1(k<<,l,mid),find1(k<<|,mid+,r);
pushup(k);
return;
}
signed main(){
n=read(),q=read();
for(int i=;i<=n;i++) val[i]=read();
build(,,n);
while(q--){
int opt=read(),l=read()+,r=read()+;
if(opt==) {
int w=read();
add(,,n,l,r,w);
}
if(opt==){
int w=read();
div(,,n,l,r,w);
}
if(opt==) printf("%lld\n",query_minn(,,n,l,r));
if(opt==) printf("%lld\n",query_sum(,,n,l,r));
}
}

[雅礼集训 2017 Day1]市场的更多相关文章

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

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

  2. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

  3. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  4. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

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

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

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

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

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

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

  8. 「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)

    老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有log(n)次) 于是暴力啊暴力,结果我归天了. 好吧,在各种题解的摧残下,我终于出了一篇巨好看(chou lou)代码(很多结构体党 ...

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

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

随机推荐

  1. ddms+adt+jdk的安装及调试开发安卓

    _______ ddms+adt+jdk的安装及调试开发安卓 目录 阐述 1 1  jdk安装 1 2  sdk安装 3 3  Eclipse安装 6 4  ADT安装 10 5  Ddms使用 16 ...

  2. 搭建RTSP服务器时nginx的nginx.conf文件配置

    worker_processes 1; events { worker_connections 1024;} http { include mime.types; default_type appli ...

  3. python程序设计——面向对象程序设计:继承

    继承是为代码复用和设计复用而设计的 在继承关系中,已有的.设计好的类称为父类或基类,新设计的类为子类或派生类 派生类可以继承父类的公有成员,但不能继承其私有成员 如果需要在派生类中调用基类的方法,可以 ...

  4. 简单在kubernetes中安装cadvisor

    cadvisor用于分析docker资源占用情况及性能的工具 安装命令: docker run --volume=/:/rootfs:ro --volume=/: --detach=true --na ...

  5. LeetCode--147.对链表进行插入排序

    题目描述: 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插入排序算法 ...

  6. spring第一章

    spring第一章 一.概述 Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的 ...

  7. Python os.makedirs() 方法

    os.makedirs() 方法用于递归创建目录.像 mkdir(), 但创建的所有intermediate-level文件夹需要包含子目录. 语法 makedirs()方法语法格式如下: os.ma ...

  8. 希尔排序(java实现)

    上篇blog中介绍的直接插入排序,希尔排序就是对直接插入排序的一个优化.比如有这么一种情况:对一个无序数组进行从小到大的排序,但是数组的最后一个位置的数是最小的,我们要把它挪到第一个位置,其他位置的都 ...

  9. caffe环境搭建笔记

    首先安装以下库或软件 sudo apt-get install gitsudo apt-get install      libprotobuf-dev     libleveldb-dev    l ...

  10. vue-cli脚手架搭建

    我们使用vue-cli来搭建整个项目,vue-cli就是一个脚手架,步骤很简单,输入几个命令之后就会生成整个项目,里面包括了webpack.ESLint.babel很多配置等等,省了很多事 Vue+ ...