线段树练习5(codevs 4927)
有n个数和5种操作
add a b c:把区间[a,b]内的所有数都增加c
set a b c:把区间[a,b]内的所有数都设为c
sum a b:查询区间[a,b]的区间和
max a b:查询区间[a,b]的最大值
min a b:查询区间[a,b]的最小值
第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述
对于所有的sum、max、min询问,一行输出一个答案
10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6
49
11
4
10%:1<n,m<=10
30%:1<n,m<=10000
100%:1<n,m<=100000
保证中间结果在long long(C/C++)、int64(pascal)范围内
/*
线段树的裸题,用分块写略麻烦。
对于每个块维护两个标记,添加标记和修改标记,修改的时候对于完整的块只修改标记,对于不完整的块,暴力修改,查询也是一样。
*/
#include<cstdio>
#include<iostream>
#include<cmath>
#define N 100010
#define inf 1000000000
#define lon long long
using namespace std;
int val[N],mx[N],mn[N],tag1[N],tag2[N],bl[N],n,m,len;lon sum[N]; void pushdown(int k){
if(tag2[k]!=-){
for(int i=(k-)*len+;i<=min(k*len,n);i++)
val[i]=tag2[k];
tag1[k]=;tag2[k]=-;
}
if(tag1[k]){
for(int i=(k-)*len+;i<=min(k*len,n);i++)
val[i]+=tag1[k];
tag1[k]=;
}
} void modify(int x,int y,int z){
//下放x不完整区间
int k=bl[x];pushdown(k);
for(int i=x;i<=min(k*len,y);i++) val[i]+=z;
sum[k]=;mx[k]=-inf;mn[k]=inf;
for(int i=(k-)*len+;i<=min(k*len,n);i++)
sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
//下放完整区间
for(int i=bl[x]+;i<bl[y];i++){
if(tag2[i]!=-) tag2[i]+=z;
else tag1[i]+=z;
sum[i]+=(lon)z*(lon)len;mx[i]+=z;mn[i]+=z;
}
//下放y不完整区间
if(bl[x]==bl[y]) return;
k=bl[y];pushdown(k);
for(int i=(k-)*len+;i<=y;i++) val[i]+=z;
sum[k]=;mx[k]=-inf;mn[k]=inf;
for(int i=(k-)*len+;i<=min(k*len,n);i++)
sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
} void change(int x,int y,int z){
//下放x不完整区间
int k=bl[x];pushdown(k);
for(int i=x;i<=min(k*len,y);i++) val[i]=z;
sum[k]=;mx[k]=-inf;mn[k]=inf;
for(int i=(k-)*len+;i<=min(k*len,n);i++)
sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
//下方完整区间
for(int i=bl[x]+;i<bl[y];i++)
tag2[i]=mx[i]=mn[i]=z,sum[i]=(lon)z*(lon)len,tag1[i]=;
//下放y不完整区间
if(bl[x]==bl[y]) return;
k=bl[y];pushdown(k);
for(int i=(k-)*len+;i<=y;i++) val[i]=z;
sum[k]=;mx[k]=-inf;mn[k]=inf;
for(int i=(k-)*len+;i<=min(k*len,n);i++)
sum[k]+=(lon)val[i],mx[k]=max(mx[k],val[i]),mn[k]=min(mn[k],val[i]);
} lon querysum(int x,int y){
lon tot=;int k=bl[x];
pushdown(k);
for(int i=x;i<=min(k*len,y);i++) tot+=(lon)val[i];
for(int i=bl[x]+;i<bl[y];i++) tot+=sum[i];
if(bl[x]==bl[y]) return tot;
k=bl[y];pushdown(k);
for(int i=(k-)*len+;i<=y;i++) tot+=(lon)val[i];
return tot;
} int querymax(int x,int y){
int maxn=-inf,k=bl[x];
pushdown(k);
for(int i=x;i<=min(k*len,y);i++) maxn=max(maxn,val[i]);
for(int i=bl[x]+;i<bl[y];i++) maxn=max(maxn,mx[i]);
if(bl[x]==bl[y]) return maxn;
k=bl[y];pushdown(k);
for(int i=(k-)*len+;i<=y;i++) maxn=max(maxn,val[i]);
return maxn;
} int querymin(int x,int y){
int minn=inf,k=bl[x];
pushdown(k);
for(int i=x;i<=min(k*len,y);i++)minn=min(minn,val[i]);
for(int i=bl[x]+;i<bl[y];i++) minn=min(minn,mn[i]);
if(bl[x]==bl[y]) return minn;
k=bl[y];pushdown(k);
for(int i=(k-)*len+;i<=y;i++) minn=min(minn,val[i]);
return minn;
} int main(){
scanf("%d%d",&n,&m);
len=sqrt(n);
for(int i=;i<=n/len+;i++){
mx[i]=-inf;
mn[i]=inf;
tag2[i]=-;
}
for(int i=;i<=n;i++){
scanf("%d",&val[i]);
bl[i]=(i-)/len+;
mx[bl[i]]=max(mx[bl[i]],val[i]);
mn[bl[i]]=min(mn[bl[i]],val[i]);
sum[bl[i]]+=(lon)val[i];
}
char op[];int x,y,z;
for(int i=;i<=m;i++){
scanf("%s%d%d",op,&x,&y);
if(op[]=='d'||op[]=='t') scanf("%d",&z);
if(op[]=='d') modify(x,y,z);
if(op[]=='t') change(x,y,z);
if(op[]=='m') printf("%lld\n",querysum(x,y));
if(op[]=='x') printf("%d\n",querymax(x,y));
if(op[]=='n') printf("%d\n",querymin(x,y));
}
return ;
}
线段树练习5(codevs 4927)的更多相关文章
- AC日记——线段树练习5 codevs 4927
4927 线段树练习5 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 有n个数和5种操作 add a b ...
- T1081 线段树练习 2 codevs
http://codevs.cn/problem/1081/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数, ...
- AC日记——线段树练习三 codevs 1082 (分块尝试)
线段树练习 3 思路: 分块: 来,上代码: #include <cmath> #include <cstdio> #include <cstring> #incl ...
- AC日记——线段树练习4 codevs 4919
4919 线段树练习4 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 给你N个数,有两种操作 ...
- T1082 线段树练习3 codevs
http://codevs.cn/problem/1082/ 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 ...
- codevs 1080 线段树练习 CDQ分治
codevs 1080 线段树练习 http://codevs.cn/problem/1080/ 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 一行N个 ...
- Codevs 4927 线段树练习5(分块)
4927 线段树练习5 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有n个数和5种操作 add a b c:把区间[a,b]内的 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
随机推荐
- 关于在filter中获取WebApplicationContext的实践
网上很多说法,诸如: <param-name>contextConfigLocation</param-name> <param-value> classpath: ...
- 反射机制与IOC容器
原文地址:http://blog.csdn.net/u010926964/article/details/47262771
- Solr笔记(2)_Schema.xml和solrconfig.xml分析
现在我们开始研究载入的数据部分(importing data) 在正式开始前,我们先介绍一个存储了大量音乐媒体的网站http://musicbrainz.org , 这里的数据都是免费的,一个大型开放 ...
- LeetCode || 大杂烩w
454. 4Sum II 题意:给四个数组,每个数组内取一个数使得四个数和为0,问有多少种取法 思路:枚举为On4,考虑两个数组,On2枚举所有可能的和,将和的出现次数存入map中,On2枚举另两个数 ...
- 关于回顾css发现的一些问题
1.针对于before和after伪元素的用法: <style> .clearfix:before, .clearfix:after{ clear:both; content:" ...
- Spring-2-官网学习
spring生命周期回调 结合生命周期机制(官网提供) 1.实现InitializingBean接口重写void afterPropertiesSet() throws Exception;方法 使用 ...
- Python内置方法详解
1. 字符串内置方法详解 为何要有字符串?相对于元组.列表等,对于唯一类型的定义,字符串具有最简单的形式. 字符串往往以变量接收,变量名. 可以查看所有的字符串的内置方法,如: 1> count ...
- Spring中使用注解 @Scheduled 执行定时任务
来自:http://blog.51cto.com/dwf07223/1557145 注解@Scheduled 可以作为一个触发源添加到一个方法中,例如,以下的方法将以一个固定延迟时间5秒钟调用一次执行 ...
- 【http】http协议的队首阻塞
1 队首阻塞 就是需要排队,队首的事情没有处理完的时候,后面的人都要等着. 2 http1.0的队首阻塞 对于同一个tcp连接,所有的http1.0请求放入队列中,只有前一个请求的响应收到了,然后才能 ...
- u-boot顶层Makefile分析
1.u-boot制作命令 make forlinx_nand_ram256_config: make all; 2.顶层mkconfig分析,参考 U-BOOT顶层目录mkconfig分析 mkcon ...