线段树练习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] .根 ...
随机推荐
- Window10 开启传统启动界面
Windows 10沿袭了Windows 8的快速启动,导致在启动过程中无法通过按F8进入启动选项,这样当系统遇到问题无法进入时根本无法通过进入安全模式等方式进行处理(当然通过其他一些工具还是能够引导 ...
- Android(java)学习笔记140:常用的对话框
一.常见对话框属性: 1. AlertDialog.Builder属性 • setTitle: 为对话框设置标题 :• setIcon : 为对话框设置图标:• setMessage: 为对话框设置 ...
- 如何关闭OSX 10.11 SIP (System Integrity Protection)
http://www.jianshu.com/p/0572336a0771 注意:SIP功能是Apple在OSX上推出的系统完整性保护功能,对于普通MAC用户来说是一项安全保护功能,如果不了解他的作用 ...
- Windows MinGW 64-bit boost 踩坑
>g++ -Wall -shared -g -DBUILD_DLL main.cpp -ID:\gcc\boost\include\boost-1_69 -LD:\gcc\boost\lib - ...
- lucene4.10.2实例(增删改查)
最新jar和src免费下载:http://download.csdn.net/detail/u011518709/8248403 lucene 包的组成结构:对于外部应用来说索引模块(index)和检 ...
- Linux网卡设置为网桥模式
Linux网卡设置为网桥模式 1. 添加网卡,并修改相关配置文件 1.1虚拟机添加网卡,并配置相关文件 如:eth2为新添加网卡 cd /etc/sysconfig/network-script ...
- Ruby设计模式-观察者模式学习笔记
observer.rb #!/bin/env ruby # encoding: utf-8 require 'observer' class CriminalMovement include Obse ...
- HDU - 4802 - GPA (水题)
题意: 计算GPA,输入一个数字和一个字符串,用 数字×字符串对应的数值 思路: 用map对应数值,要注意的是字符串为P或者N的时候,不计入结果 代码: #include<iostream> ...
- hihoCoder-1089-Floyd
我们读入的时候,要考虑重边的问题,我们只取边的最小值就可以了. #include <cstdio> #include <cstring> const int INF = 0x3 ...
- nginx 部署ssl证书之后访问用火狐出现SSL_ERROR_RX_RECORD_TOO_LONG此错误,用Google出现ERR_SSL_PROTOCOL_ERROR错误
server { listen ; server_name xxx.com; ssl_certificate ssl/xxx.pem; ssl_certificate_key ssl/xxx.key; ...