传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001

WZJ的数据结构(十)
难度级别:D; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

请你设计一个数据结构,高效执行以下过程:

#include<iostream>
using namespace std;
const int maxn=100010;
int A[maxn];
int tp,ql,qr,v;
int _max,_min,_sum;
int main()
{
 int n,Q,tp;
 cin>>n>>Q;
 for(int i=1;i<=n;i++) cin>>A[i];
 while(Q--)
 {
  cin>>tp>>ql>>qr;
  if(tp==2)
  {
   _sum=0; _max=-1000000000; _min=1000000000;
   for(int i=ql;i<=qr;i++)
   {
    _max=max(_max,A[i]);
    _min=min(_min,A[i]);
    _sum+=A[i];
   }
   cout<<_max<<" "<<_min<<" "<<_sum<<endl;
  }
  else
  {
   cin>>v;
   for(int i=ql;i<=qr;i++)
   {
    if(!tp) A[i]=0;
    A[i]+=v;
   }
  }
 }
 return 0;
}

输入
见代码
输出
见代码
输入示例
5 5
1 2 3 4 5
2 1 3
0 1 5 2
1 2 3 3
2 1 4
2 1 5
输出示例
3 1 6
5 2 14
5 2 16
其他说明
1<=n,Q<=100000
0<=tp<=2
1<=A[i],v<=1000
1<=ql<=qr<=n

指针版线段树:

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
#define CH for(int d=0;d<=1;d++) if(ch[d])
using namespace std;
const int maxn=+,maxnode=+,inf=-1u>>;
struct node{
node*ch[];int mi,mx,sm,add,set,siz;node(){mi=inf;mx=-inf;sm=add=;set=inf;}
void sett(int tag){mi=mx=set=tag;sm=tag*siz;add=;return;}
void addt(int tag){add+=tag;mi+=tag;mx+=tag;sm+=tag*siz;return;}
void down(){
if(set!=inf){CH{ch[d]->sett(set);}set=inf;}
if(add){CH{ch[d]->addt(add);}add=;}
return;
}
void update(){
mi=inf;mx=-inf;sm=;
CH{mi=min(mi,ch[d]->mi);mx=max(mx,ch[d]->mx);sm+=ch[d]->sm;}
return;
}
}seg[maxnode],*nodecnt=seg,*root;
int A[maxn],ql,qr,cv,tp;
void build(node*&x,int L,int R){
x=nodecnt++;
if(L==R) x->mi=x->mx=x->sm=A[L];
else{
int M=L+R>>;
build(x->ch[],L,M);
build(x->ch[],M+,R);
x->update();
} x->siz=R-L+;return;
}
void update(node*&x,int L,int R){
if(ql<=L&&R<=qr){
if(tp) x->addt(cv);
else x->sett(cv);
}
else{
int M=L+R>>;
x->down();
if(ql<=M) update(x->ch[],L,M);
if(qr>M) update(x->ch[],M+,R);
x->update();
}
return;
}
int _mi,_mx,_sm;
void query(node*x,int L,int R){
if(ql<=L&&R<=qr){
_mi=min(_mi,x->mi);
_mx=max(_mx,x->mx);
_sm+=x->sm;
}
else{
int M=L+R>>;
x->down();
if(ql<=M) query(x->ch[],L,M);
if(qr>M) query(x->ch[],M+,R);
} return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
int n,Q;
void init(){
n=read();Q=read();
for(int i=;i<=n;i++) A[i]=read();
build(root,,n);
return;
}
void work(){
char ch;
while(Q--){
tp=read();ql=read();qr=read();
if(tp!=){
cv=read();
update(root,,n);
}
else{
_mi=inf;_mx=-inf;_sm=;
query(root,,n);
write(_mx);PAU;write(_mi);PAU;write(_sm);ENT;
}
}
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}

题解:传两个lazy标:setv,addv,addv是建立在setv上的增加量,这样来一个setv就清掉addv,来一个addv就加上去,维护懒标的时候先维护setv再维护addv就好了。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
const int maxn=+,maxn3=+,inf=-1u>>;
int maxv[maxn3],minv[maxn3],sumv[maxn3],setv[maxn3],addv[maxn3],A[maxn];
void pushup(int o,int lc,int rc){
minv[o]=min(minv[lc],minv[rc]);
maxv[o]=max(maxv[lc],maxv[rc]);
sumv[o]=sumv[lc]+sumv[rc];
return;
}
void pushdown(int o,int lc,int rc){
if(setv[o]>=){
setv[lc]=setv[rc]=setv[o];
addv[lc]=addv[rc]=;
setv[o]=-;
} if(addv[o]){
addv[lc]+=addv[o];
addv[rc]+=addv[o];
addv[o]=;
} return;
}
void maintain(int o,int L,int R){
int lc=o<<,rc=lc|;
if(L<R&&setv[o]<) pushup(o,lc,rc);
if(setv[o]>=){
minv[o]=maxv[o]=setv[o];
sumv[o]=(R-L+)*setv[o];
} if(addv[o]){
minv[o]+=addv[o];
maxv[o]+=addv[o];
sumv[o]+=(R-L+)*addv[o];
} return;
}
int _min,_max,_sum,ql,qr,tp,cv;
void update(int o,int L,int R){
if(ql<=L&&R<=qr){
if(tp) addv[o]+=cv;
else setv[o]=cv,addv[o]=;
} else{
int M=L+R>>,lc=o<<,rc=lc|;
pushdown(o,lc,rc);
if(ql<=M) update(lc,L,M); else maintain(lc,L,M);
if(qr>M) update(rc,M+,R); else maintain(rc,M+,R);
} maintain(o,L,R);return;
}
void build(int o,int L,int R){
if(L==R) setv[o]=A[L];
else{
int M=L+R>>,lc=o<<,rc=lc|;
build(lc,L,M);build(rc,M+,R);
} maintain(o,L,R);return;
}
void query(int o,int L,int R,int add){
if(setv[o]>=){
int change=setv[o]+addv[o]+add;
_sum+=(min(R,qr)-max(L,ql)+)*change;
_min=min(_min,change);
_max=max(_max,change);
} else if(ql<=L&&R<=qr){
_sum+=sumv[o]+(R-L+)*add;
_min=min(_min,minv[o]+add);
_max=max(_max,maxv[o]+add);
} else{
int M=L+R>>,lc=o<<,rc=lc|;
if(ql<=M) query(lc,L,M,add+addv[o]);
if(M<qr) query(rc,M+,R,add+addv[o]);
} return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
int n,Q;
void init(){
memset(setv,-,sizeof(setv));
n=read();Q=read();
for(int i=;i<=n;i++) A[i]=read();
build(,,n);
return;
}
void work(){
while(Q--){
tp=read();ql=read();qr=read();
if(tp==){//query
_sum=;_min=inf;_max=-inf;
query(,,n,);
write(_max);PAU;write(_min);PAU;write(_sum);ENT;
} else cv=read(),update(,,n);
}
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}

然而分块大法好!注意query一块内是不用down的。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
const int maxn=+,maxb=,inf=-1u>>;
int mi[maxb],mx[maxb],sm[maxb],st[maxb],en[maxb],A[maxn],set[maxb],add[maxb],b[maxn],siz[maxb],n,Q,size;
int _mi,_mx,_sm;
void update(int L,int R){
int i=b[L];if(b[L]!=b[R]) abort();
if(set[i]!=inf) _mi=min(_mi,set[i]+add[i]),_mx=max(_mx,set[i]+add[i]),_sm+=(set[i]+add[i])*(R-L+);
else{
for(int j=L;j<=R;j++){
_mi=min(_mi,A[j]+add[i]);
_mx=max(_mx,A[j]+add[i]);
_sm+=A[j]+add[i];
}
}return;
}
void updateb(int L,int R){
for(int b=L;b<=R;b++){
_mi=min(_mi,mi[b]);
_mx=max(_mx,mx[b]);
_sm+=sm[b];
} return;
}
void update(int b){
bool se=set[b],ad=add[b];
if(se&&ad) _mi=_mx=set[b]+add[b];
}
void build(int b){
mi[b]=inf;mx[b]=-inf;sm[b]=;
for(int i=st[b];i<=en[b];i++){
mi[b]=min(mi[b],A[i]);
mx[b]=max(mx[b],A[i]);
sm[b]+=A[i];
}return;
}
void addt(int L,int R,int cv){for(int i=L;i<=R;i++) A[i]+=cv;build(b[L]);return;}
void sett(int L,int R,int cv){for(int i=L;i<=R;i++) A[i]=cv;build(b[L]);return;}
void addb(int L,int R,int cv){
for(int b=L;b<=R;b++) add[b]+=cv,mi[b]+=cv,mx[b]+=cv,sm[b]+=cv*siz[b];return;
}
void setb(int L,int R,int cv){
for(int b=L;b<=R;b++) set[b]=cv,add[b]=,mi[b]=cv,mx[b]=cv,sm[b]=cv*siz[b];return;
}
void down(int b){
if(set[b]!=inf) sett(st[b],en[b],set[b]);
if(add[b]) addt(st[b],en[b],add[b]);
set[b]=inf;add[b]=;return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') sig=-;ch=getchar();}
while(isdigit(ch)) x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<) putchar('-'),x=-x;
int len=,buf[];while(x) buf[len++]=x%,x/=;
for(int i=len-;i>=;i--) putchar(buf[i]+'');return;
}
void init(){
n=read();Q=read();size=(int)sqrt(n);
for(int i=;i<=n;i++){
A[i]=read();
b[i]=(i-)/size+;
if(!st[b[i]]) st[b[i]]=i;
en[b[i]]=i;
}
for(int i=b[n];i>=;i--) siz[i]=en[i]-st[i]+;
for(int i=b[n];i>=;i--) build(i);
for(int i=;i<=b[n];i++) set[i]=inf;
return;
}
void work(){
int tp,ql,qr,cv;
while(Q--){
tp=read();ql=read();qr=read();
if(tp==){
_mi=inf;_mx=-inf;_sm=;
if(b[ql]==b[qr]) update(ql,qr);
else{updateb(b[ql]+,b[qr]-);update(ql,en[b[ql]]);update(st[b[qr]],qr);}
write(_mx);PAU;write(_mi);PAU;write(_sm);ENT;
}else if(tp){
cv=read();if(b[ql]==b[qr]) down(b[ql]),addt(ql,qr,cv);
else{addb(b[ql]+,b[qr]-,cv);down(b[ql]);down(b[qr]);addt(ql,en[b[ql]],cv);addt(st[b[qr]],qr,cv);}
}else{
cv=read();if(b[ql]==b[qr]) down(b[ql]),sett(ql,qr,cv);
else{setb(b[ql]+,b[qr]-,cv);down(b[ql]);down(b[qr]);sett(ql,en[b[ql]],cv);sett(st[b[qr]],qr,cv);}
}
}
return;
}
void print(){
return;
}
int main(){
init();work();print();return ;
}

COJ 1010 WZJ的数据结构(十) 线段树区间操作的更多相关文章

  1. Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...

  2. POJ 2528 ——Mayor's posters(线段树+区间操作)

    Time limit 1000 ms Memory limit 65536 kB Description The citizens of Bytetown, AB, could not stand t ...

  3. COJ 1008 WZJ的数据结构(八) 树上操作

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=986 WZJ的数据结构(八) 难度级别:E: 运行时间限制:3000ms: ...

  4. COJ 1007 WZJ的数据结构(七) 树上操作

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=983 WZJ的数据结构(七) 难度级别:C: 运行时间限制:1000ms: ...

  5. 线段树(区间操作) POJ 3325 Help with Intervals

    题目传送门 题意:四种集合的操作,对应区间的01,问最后存在集合存在的区间. 分析:U T [l, r]填充1; I T [0, l), (r, N]填充0; D T [l, r]填充0; C T[0 ...

  6. POJ 3225 Help with Intervals --线段树区间操作

    题意:给你一些区间操作,让你输出最后得出的区间. 解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题. 线段树维护两个值: cov ...

  7. HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)

    http://acm.hdu.edu.cn/showproblem.php?pid=6315 题意 a数组初始全为0,b数组为1-n的一个排列.q次操作,一种操作add给a[l...r]加1,另一种操 ...

  8. HDU 4578——Transformation——————【线段树区间操作、确定操作顺序】

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  9. 吉首大学校赛 K 白山茶与红玫瑰 (线段树区间操作)

    链接:https://ac.nowcoder.com/acm/contest/925/K来源:牛客网 题目描述 公元2019年6月22日,白山茶王国与红玫瑰王国展开大战,在世外仙境——天空花园处,双方 ...

随机推荐

  1. JNI调用native方法出现 java.lang.UnsatisfiedLinkError: XXXclass.XXXmethod()异常的解决办法

    昨天拿到JNI的Android工程Demo,然后把demo整合到开发的主线工程上,发现调用JNI方法一直抛同一个异常 java.lang.UnsatisfiedLinkError: XXXclass. ...

  2. 用java具体代码实现分数(即有理数)四则运算

    用java具体代码实现分数(即有理数)四则运算 1,背景 Java老师布置了一个关于有理数运算的题目,因为参考书上有基本代码,所以自己主要是对书上代码做了一点优化,使其用户交互性更加友好以及代码封装性 ...

  3. Android笔记之 文件保存、压缩与清空删除

    这两天改进优化项目中图片上传的代码.考虑到可能有7.8M的比較大的图片,由于要先进行压缩.所以设计到文件的压缩,保存与清空删除操作. 在这里记下笔记. /** * 压缩并另存为,每次先清空再保存 */ ...

  4. java实现excel的导入导出(poi详解)

    经过两天的研究,现在对excel导出有点心得了.我们使用的excel导出的jar包是poi这个阿帕奇公司的一个项目,后来被扩充了.是比较好用的excel导出工具. 下面来认识一下这个它吧. 我们知道要 ...

  5. IOS后台执行机制 与 动作

    当用户按下"Home"键或者系统启动另外一个应用时,前台foreground应用首先切换到Inactive状态,然后切换到Background状态.此转换将会导致先后调用应用代理的 ...

  6. Android TagFlowLayout完全解析 一款针对Tag的布局(转)

    一.概述 本文之前,先提一下关于上篇博文的100多万访问量请无视,博文被刷,我也很郁闷,本来想把那个文章放到草稿箱,结果放不进去,还把日期弄更新了,实属无奈. ok,开始今天的博文,今天要说的是Tag ...

  7. Java基础知识强化97:final、finally、finally区别

    1. final修饰符(关键字)     如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此,一个类不能既被声明为abstract,又被声明为final.     将 ...

  8. Java中字符串内存位置浅析

    前言 之前写过一篇关于JVM内存区域划分的文章,但是昨天接到蚂蚁金服的面试,问到JVM相关的内容,解释一下JVM的内存区域划分,这部分答得还不错,但是后来又问了Java里面String存放的位置,之前 ...

  9. css 实现文字过长变成省略号(包含单行的and多行的)

    单行的比较简单  但是必须条件同时满足 <DIV STYLE="width: 120px; height: 50px; border: 1px solid blue;overflow: ...

  10. .Net程序员 Solr-5.3之旅 (二)Solr 安装

    阅读目录 引言 Solr5.3环境搭建 Solr5.3创建第一个Core 结尾 引言 一个糟糕的设计有好的表现形式,它会被判死缓,一个好的设计有糟糕的表现形式,它会被判死刑立即执行. 以上摘自一个设计 ...