博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【loj6029】「雅礼集训 2017 Day1」市场
阅读量:5336 次
发布时间:2019-06-15

本文共 3594 字,大约阅读时间需要 11 分钟。

题意:四种操作,区间加法、区间除法(下取整)、区间求最小值、区间求和。

第1、3、4个操作都是摆设,关键在于如何做区间除法。

很明显不能直接把区间的和做除法后向下取整,因为区间和可能会多凑出一个除数因子。例如$3,3$,对这两个数的区间除以2取整后变成$1,1$,但如果直接把它们的和6除以2取整后得到的和是3,很明显有误。

但是根据经验,带有区间除法操作的题目一般都会把数给你往小了压。再一看这题,两个修改操作中,区间加法的加数不大且可能是负数,而除数可高达$10^9$!

尤其是除法的大除数带来的影响特别大,这实际上暗示我们序列的数很容易迅速被压到0附近。而数的绝对值被压到很小,除数却有很大时,我们发现实际上这些数的变化可能会很小。小到什么程度呢?

考虑如果有一些近似连续的小数段,

比如$2,2,2,3,3,3$,在除3意义下,变成$0,0,0,1,1,1$,相当于整体-2。

在序列的数都被压到足够接近0时,很容易出现上面这种序列,此时就可以用区间加法维护上面这种区间的除法操作了!

那怎么判断除法区间的所有数的变化量是否相同呢?只需判断最大值和最小值的变化量是否相同即可。原因:除法区间的数按从小到大的顺序,数的变化量是单调不下降的(大数和小数都被同一个大于等于$1$的正数(题目说了除数在$[2,10^9]$范围内)除,大数当然还比小数大,变化量也比小数大,即使是在向下取整的意义下,大数仍不会比小数小,变化量也不会比小数小(为什么除数是在$(0,1)$范围内的正数时 "变化量也不会比小数小" 这条不成立,请自行思考,如果想明白了你也就明白为什么除数是大于等于$1$的正数时这条成立了)),所以只要看两端的最小值和最大值的变化量是否相同就能知道整个区间的数的变化量是否相同。

归根结底区间除法转化成了区间加法+区间最大值+区间最小值,于是还需要维护一下原题没有要求的区间最大值。

 

1 #include
2 #define N 100001 3 #define inf 0x7f7f7f7f7f7f7f7f 4 using namespace std; 5 inline int read(){ 6 int x=0; bool f=1; char c=getchar(); 7 for(;!isdigit(c);c=getchar()) if(c=='-') f=0; 8 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0'); 9 if(f) return x; 10 return 0-x; 11 } 12 int n,q; 13 long long a[N],mx[N<<2],mn[N<<2],sum[N<<2],tag[N<<2]; 14 int L,R,x; 15 inline void pushup(int o){ 16 sum[o]=sum[o<<1]+sum[o<<1|1]; 17 mx[o]=max(mx[o<<1],mx[o<<1|1]); 18 mn[o]=min(mn[o<<1],mn[o<<1|1]); 19 } 20 void pushdown(int o,int l,int r){ 21 if(!tag[o] || l==r) return; 22 //printf("pushdown:%d %d %d %d %d\n",o,l,r,tag[o],mn[o]); 23 int mid=(l+r)>>1; 24 sum[o<<1]+=(mid-l+1)*tag[o], sum[o<<1|1]+=(r-mid)*tag[o]; 25 mx[o<<1]+=tag[o], mx[o<<1|1]+=tag[o]; 26 mn[o<<1]+=tag[o], mn[o<<1|1]+=tag[o]; 27 tag[o<<1]+=tag[o], tag[o<<1|1]+=tag[o]; //严重错因,好几个小时才查出这里直接覆盖儿子tag值的错误,一定要铭记! 28 tag[o]=0; 29 } 30 void build(int o,int l,int r){ 31 //printf("%d %d %d\n",o,l,r); system("pause"); 32 if(l==r){sum[o]=mx[o]=mn[o]=a[l]; return;} 33 int mid=(l+r)>>1; 34 build(o<<1,l,mid), build(o<<1|1,mid+1,r); 35 pushup(o); 36 } 37 void add(int o,int l,int r){ 38 //printf("query:%d %d %d %d\n",l,r,mn[o],tag[o]); 39 if(L<=l && r<=R){ 40 tag[o]+=x, sum[o]+=(long long)(r-l+1)*x, mx[o]+=x, mn[o]+=x; 41 return; 42 } 43 pushdown(o,l,r); 44 int mid=(l+r)>>1; 45 if(L<=mid) add(o<<1,l,mid); 46 if(mid
>1; 54 long long ret=inf; 55 if(L<=mid) ret=min(ret,min_query(o<<1,l,mid)); 56 if(mid
>1; 72 if(L<=mid) div(o<<1,l,mid); 73 if(mid
>1; 81 long long ret=0; 82 if(L<=mid) ret+=sum_query(o<<1,l,mid); 83 if(mid
>1; 92 find(o<<1,l,mid), find(o<<1|1,mid+1,r); 93 pushup(o); 94 } 95 96 int main(){ 97 //freopen("rand.in","r",stdin); 98 //freopen("count.out","w",stdout); 99 n=read(),q=read();100 int i,k;101 for(i=1;i<=n;i++) a[i]=read();102 build(1,1,n);103 for(i=1;i<=q;i++){104 k=read(),L=read()+1,R=read()+1;105 if(k==1) x=read(), add(1,1,n);106 else if(k==2) x=read(), div(1,1,n);107 else if(k==3) printf("%lld\n",min_query(1,1,n));108 else if(k==4) printf("%lld\n",sum_query(1,1,n));109 //find(1,1,n);110 //putchar('\n');putchar('\n');putchar('\n');putchar('\n');111 }112 return 0;113 }114 /*115 10 11116 1 2 3 4 5 6 7 8 9 10117 2 0 9 2118 2 0 9 3119 2 0 9 4120 2 0 9 5121 2 0 9 6122 3 0 9123 4 0 9124 1 0 4 -4125 2 0 4 2126 3 0 4127 4 0 9128 */
View Code

 

转载于:https://www.cnblogs.com/scx2015noip-as-php/p/loj6029.html

你可能感兴趣的文章
麻省理工MaKey MaKey的电路板,触控无处不在,很强大。
查看>>
关于leap motion的原理和疑点
查看>>
Web前端,高性能优化
查看>>
【转载】Recommendations with Thompson Sampling (Part II)
查看>>
UML
查看>>
Javascript中decodeURI()与decodeURIComponent()区别
查看>>
redis设置开机启动
查看>>
Web GIS
查看>>
SpringBoot搭建简单的web项目及Echarts地图demo
查看>>
Spark随笔(三):straggler的产生原因
查看>>
android中TextView中文字体粗体的方法
查看>>
sealed(C# 参考)
查看>>
Golang Import使用入门
查看>>
postgresql 获取主键字段
查看>>
GNU libmicrohttpd 0.9.24 发布
查看>>
响应式网站
查看>>
Less环境搭建
查看>>
openstack trove mongodb配置项
查看>>
poj 3481 Double Queue 数据结构 STL
查看>>
线段树模板
查看>>