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 ...
随机推荐
- 实例化Model的三种方式
- 介绍Git版本控制器的使用
Git 简介 Git 是什么?大家肯定会说不就是版本控制器嘛,是的Git是目前世界上最先进的分布式版本控制系统(没有之一). 1.那什么是版本控制器呢? 举个简单的例子,比如我们用Word写文章,那你 ...
- Node.js之Promise
2015年发布了ES6标准,所谓 Promise,就是ES6标准的一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步 ...
- Android Home键状态保存运用场景
当我们在一个Activity中有接收Intent过来的值,或者当前Activity有保存数据时候,如果此时不小心按到了Home键,然后没有及时回来而是运行了其它应用程序,当你想起来的时候,恐怕已经是几 ...
- 第十章实践——系统级I/O代码运行
第十章实践——系统级I/O代码运行 实验代码清单如下: 1. cp1——复制一个文件到另一个文件中(两个已经存在的文件) 复制前: 执行后结果 2. setecho.echostate——改变.显示输 ...
- 【MPI学习1】简单MPI程序示例
有了apue的基础,再看mpi程序多进程通信就稍微容易了一些,以下几个简单程序来自都志辉老师的那本MPI的书的第七章. 现在ubuntu上配置了一下mpich的环境: http://www.cnblo ...
- Java问题:Quartz,Hibernate,Spring,Tomcat中定时任务无故停止,没有错误
最近在做一个java项目的时候遇到一个十分奇怪的问题,想到大家可能也会遇到这样的问题,所以在此发出来,希望大家遇到的时候能够快速解决! 直入主题 问题:使用quartz进行定时任务自动执行的时候,用到 ...
- [bzoj 1064][NOI2008]假面舞会(dfs判断环)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1064 分析: 如果a看到b,则a->b 那么: 1.如果图中有环,则说明这个环的 ...
- WEB前端开发规范
WEB前端开发规范 规范目的 为提高团队协作效率, 便于后台人员添加功能及前端后期优化维护, 输出高质量的文档, 特制订此文档.本文档如有不对或者不合适的地方请及时提出, 经讨论决定后方可更改. 基本 ...
- Java 读取文件到字符串
Java的io操作比较复杂 package cn.outofmemory.util; import java.io.BufferedReader; import java.io.FileInputSt ...