「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)
老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有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」市场 (线段树除法,区间最小,区间查询)的更多相关文章
- LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法
题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...
- 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析
题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...
- #6029. 「雅礼集训 2017 Day1」市场 [线段树]
考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
- 【loj6029】「雅礼集训 2017 Day1」市场&&【uoj#228】基础数据结构练习题
题解: 这两道题加上区间取min max应该算线段树几道比较不寻常的题目 其实也是挺好理解的 对于区间/d 显然在log次后就会等于0 而我们注意到如果区间中数都相等那么就可以一起除 也就是说每个区间 ...
- 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」市场(线段树裸题)
点此看题面 大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和. 线段树维护区间除法 区间加法.区间求\(min\)和区间求和都是线段树基本操作,因此略过不提. ...
- 【loj6029】「雅礼集训 2017 Day1」市场
题目 题意:四种操作,区间加法.区间除法(下取整).区间求最小值.区间求和. 第1.3.4个操作都是摆设,关键在于如何做区间除法. 很明显不能直接把区间的和做除法后向下取整,因为区间和可能会多凑出一个 ...
随机推荐
- 基于多用户的Oracle数据泵导入导出数据
登陆SqlPlus: SqlPlus sys/syspwd@MyOrcl AS sysdba 其中:syspwd:sys的登陆密码:MyOrcl:所创建的数据库服务名. 创建数据泵: create o ...
- 09 OCP知识点讲解 之 LRU链与脏LRU链
OCP知识点讲解 之 LRU链与脏LRU链 分类: Oracle 2012-06-30 10:49:26 一.LRU链: 任何缓存的大小都是有限制的,并且总不如被缓存的数据多.就像Buffer c ...
- 产品 | What's产品经理
如果想知道什么是产品,首先需要知道什么是缔造者.其名曰:"产品经理". PS:产品经理一词在国内大多时候泛指"互联网产品经理". 对于产品经理这一职位,说实在很 ...
- iOS7下Status Bar字体颜色修改
原文来自这里:iOS7下Status Bar字体颜色修改. 旧项目在iOS7上遇到status bar字体颜色需要修改的问题,症状如下:导航栏设置为黑色后,iphone上status bar的字体颜色 ...
- C++分享笔记:扑克牌的洗牌发牌游戏设计
笔者在大学二年级期间,做过的一次C++程序设计:扑克牌的洗牌发牌游戏.具体内容是:除去大王和小王,将52张扑克牌洗牌,并发出5张牌.然后判断这5张牌中有几张相同大小的牌,是否是一条链,有几个同花等. ...
- 获取DOM
<template> <div> <header-vue :msg="msg" ref="header">heheh< ...
- tomcat安装、配置相关的几个点
Connector port="8080"HTTP协议的默认端口号:8080 FTP协议的默认端口号:21 1.tomcat的安装目录要与Java jre的安装目录一致. bin: ...
- fake_useragent 封装好user-agent的模块
from fake_useragent import UserAgent useragent = UserAgent()print(useragent.random)
- 常量的三种定义方式和static在c语言中的三种修饰
c语言的常量在执行期间为固定值,在定义后无法被修改常量可以是任何的数据基本类型,可以为整形,浮点常量,字符和字符串常量1,使用const关键字2, 使用宏定义3,使用枚举常量 枚举: #include ...
- C++ STL lower_bound()和upper_bound()
lower_bound()和upper_bound()用法 1.在数组上的用法 假设a是一个递增数组,n是数组长度,则 lower_bound(a, a+n, x):返回数组a[0]~a[n-1]中, ...