codevs4927 线段树练习5
有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)范围内
正解:线段树
解题报告:
这就是传说中的线段树综合题,所有标记都有。
注意一点,就是我的执行顺序是先add标记下传,然后才是set标记下传,但下传过程中set可以覆盖add。开始我一直WA,后来才发现了一个错误,就是我先执行的add,那么,如果当前结点上此时既有set又有add,那么只能说明add一定是在set之后执行的,不然执行set的时候add早已经下传,所以我可以考虑直接把add的值直接加在set上去,就可以避免有一部分add没有发挥作用。害得我调试了半个小时。
//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
#define RG register
const int MAXN = ;
int n,m,ql,qr;
LL val,ans,inf;
char ch[];
struct node{
int l,r;
LL minl,maxl,sum,add,set;
bool flag;
}a[MAXN*]; inline LL getint(){RG LL w=,q=; char c=getchar();while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;} inline void update(RG int root){
RG int lc=root*,rc=lc+; a[root].maxl=max(a[lc].maxl,a[rc].maxl);
a[root].sum=a[lc].sum+a[rc].sum; a[root].minl=min(a[lc].minl,a[rc].minl);
} inline void build(RG int root,RG int l,RG int r){
a[root].l=l; a[root].r=r;
if(l==r) { a[root].minl=a[root].maxl=a[root].sum=getint(); return ; }
RG int mid=(l+r)/; RG int lc=root*,rc=lc+;
build(lc,l,mid); build(rc,mid+,r); update(root);
} inline void pushdown(int root,int l,int r){
if(!a[root].flag) return ; if(l==r) { a[root].flag=false; a[root].set=; return ; }
int lc=root*,rc=lc+; int mid=(l+r)/;
a[lc].set=a[rc].set=a[root].set; a[root].add=a[lc].add=a[rc].add=;
a[lc].maxl=a[rc].maxl=a[lc].minl=a[rc].minl=a[root].set;
a[lc].sum=(LL)(mid-l+)*a[root].set; a[rc].sum=(LL)(r-mid)*a[root].set; a[root].sum=a[lc].sum+a[rc].sum;
a[lc].flag=a[rc].flag=true;
a[root].set=; a[root].flag=false;
} inline void pushdown_add(RG int root,RG int l,RG int r){
if(l==r) { a[root].add=; return ; } if(a[root].add==) return ; if(a[root].flag){ a[root].set+=a[root].add; a[root].add=; return ; }//至关重要,因为add打在set的后面,这就意味着相当于我们可以把set设的值变大一点 RG int mid=(l+r)/; RG int lc=root*,rc=lc+; a[lc].add+=a[root].add; a[rc].add+=a[root].add;
a[lc].minl+=a[root].add; a[lc].maxl+=a[root].add; a[rc].minl+=a[root].add; a[rc].maxl+=a[root].add;
a[lc].sum+=a[root].add*(LL)(mid-l+); a[rc].sum+=a[root].add*(LL)(r-mid);
a[root].add=; a[root].sum=a[lc].sum+a[rc].sum;
} inline void add(RG int root,RG int l,RG int r){
pushdown_add(root,l,r); pushdown(root,l,r);
if(ql<=l && r<=qr) { a[root].add+=val; a[root].maxl+=val; a[root].minl+=val; a[root].sum+=val*(LL)(r-l+); return ; }
RG int mid=(l+r)/; RG int lc=root*,rc=lc+; if(ql<=mid) add(lc,l,mid); if(qr>mid) add(rc,mid+,r);
update(root);
} inline void update_set(RG int root,RG int l,RG int r){
if(ql<=l && r<=qr) { a[root].flag=true; a[root].minl=a[root].maxl=a[root].set=val; a[root].add=; a[root].sum=(LL)(r-l+)*val; return ; }
pushdown_add(root,l,r); pushdown(root,l,r);
RG int mid=(l+r)/;RG int lc=root*,rc=lc+;
if(ql<=mid) update_set(lc,l,mid); if(qr>mid) update_set(rc,mid+,r); update(root);
} inline void query_sum(RG int root,RG int l,RG int r){
pushdown_add(root,l,r); pushdown(root,l,r);
if(ql<=l && r<=qr){ ans+=a[root].sum; return ; }
RG int mid=(l+r)/; RG int lc=root*,rc=lc+;
if(ql<=mid) query_sum(lc,l,mid); if(qr>mid) query_sum(rc,mid+,r); update(root);
} inline void query_max(RG int root,RG int l,RG int r){
pushdown_add(root,l,r); pushdown(root,l,r);
if(ql<=l && r<=qr){ ans=max(a[root].maxl,ans); return ; }
RG int mid=(l+r)/; RG int lc=root*,rc=lc+;
if(ql<=mid) query_max(lc,l,mid); if(qr>mid) query_max(rc,mid+,r); update(root);
} inline void query_min(RG int root,RG int l,RG int r){
pushdown_add(root,l,r); pushdown(root,l,r);
if(ql<=l && r<=qr){ ans=min(a[root].minl,ans); return ; }
RG int mid=(l+r)/; RG int lc=root*,rc=lc+;
if(ql<=mid) query_min(lc,l,mid); if(qr>mid) query_min(rc,mid+,r); update(root);
} inline void work(){
n=getint(); m=getint(); build(,,n); inf=; for(RG int i=;i<=;i++) inf*=;
while(m--) {
scanf("%s",ch);
if(ch[]=='a') { ql=getint(); qr=getint(); val=getint(); add(,,n); }
else if(ch[]=='s' && ch[]=='e') { ql=getint(); qr=getint(); val=getint(); update_set(,,n); }
else if(ch[]=='s' && ch[]=='u') { ql=getint(); qr=getint(); ans=; query_sum(,,n); printf("%lld\n",ans); }
else if(ch[]=='m' && ch[]=='a') { ql=getint(); qr=getint(); ans=-inf; query_max(,,n); printf("%lld\n",ans); }
else{ ql=getint(); qr=getint(); ans=inf; query_min(,,n); printf("%lld\n",ans); }
}
} int main()
{
work();
return ;
}
codevs4927 线段树练习5的更多相关文章
- 分块试水--CODEVS4927 线段树练习5
模板 #include<stdio.h> #include<algorithm> #include<string.h> #include<stdlib.h&g ...
- 【codevs4927】线段树练习
题目大意:维护一个序列,支持区间加.区间染色.区间最值查询.区间和查询. 题解:对于区间赋值操作来说,维护一个赋值标记,注意,这里不能直接用赋值的值直接维护,因为不像加法标记,0 表示不用处理,这里 ...
- CSU 2151 集训难度【多标记线段树】
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151 Input 第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度 ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- 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] .根 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
随机推荐
- MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引
本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...
- android应用中去掉标题栏的方法
现在我坚定的认为写技术博客对自己有很大的帮助,写博客给自己一个学而思的机会. 在Android中去掉标题栏有三种方法,它们也有各自的特点. 1.在代码里实现 this.requestWindowFea ...
- iOS下使用SHA1WithRSA算法加签源码
首先了解一下几个相关概念,以方便后面遇到的问题的解决: RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数 ...
- Tasks.Parallel
.Net多线程编程-System.Threading.Tasks.Parallel System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Paral ...
- linux命令细究
ls -ldahipFtr -t按照修改时间 -r翻转排序 /etc/profile 别名grep --color ls -pF ^$空行egrep -v "^#|^$&quo ...
- Android 中调试手段 打印函数调用栈信息
下面来简单介绍下 android 中的一种调试方法. 在 android 的 app 开发与调试中,经常需要用到打 Log 的方式来查看函数调用点. 这里介绍一种方法来打印当前栈中的函数调用关系 St ...
- Windows7+VS2012下OpenGL 4的环境配置
系统环境 Windows 7 Ultimate x64,Visual Studio Ultimate 2012 Update 4,和一块支持OpenGL 4.x的显卡. 准备工作 首先用GPU Cap ...
- 用 eric6 与 PyQt5 实现python的极速GUI编程(系列02)---- 省市县(区)下拉列表多级联动
[概览] 本文实现如下的程序: 主要步骤如下: 1.在eric6中新建项目,新建窗体 2.(自动打开)进入PyQt5 Desinger,编辑图形界面,保存 3.回到eric 6,对上一步得到的界面文件 ...
- SpringMvc学习心得(五)控制器产生与构建
SpringMvc学习心得(五)控制器产生与构建 标签: springspring mvc框架 2016-03-22 15:29 140人阅读 评论(0) 收藏 举报 分类: Spring(4) ...
- 信息安全系统设计基础_exp2
北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:1353 姓名:吴子怡.郑伟 学号:20135313.20135322 指导教师: 娄嘉鹏 实验 ...