题目传送门

考场上感觉的确是线段树,还要维护区间最值...最值怎么维护?还要区间修改?\(update\)的时候加一下就好了吧...之后怎么搞啊?\(qwqwq\)之后好像不太会了...果断删除几乎快码完的线段树,开始写\(20\)分暴力...。感觉\(20\)直接上\(O(n^3)\)算法应该可以。注意到有\(20\)分是\(op=0\),如果数据比较热心控制在\(1e5\)内,应该可以用\(ST\)表预处理,拿到就是血赚。--以上是考场心路李辰

最后:\(0\)分,\(qwq\)。

原因:可能有负边权,那么用来更新的值(也就是代码中的\(sell\))就不能是\(0\)了,应是负无穷,因为他必须买卖一次的。但是\(ans\)应该是0.这个问题在数据结构题目中应尤为注意。

#include<cstdio>
#include<algorithm>
#include<cmath> using namespace std; int n,m,ans;
int seq[100090];
int sta[100090][30]; void subtask1()
{
for(int i=1;i<=n;i++) scanf("%d",&seq[i]);
for(int i=1;i<=m;i++)
{
int op=0,x=0,y=0,z=0;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&x,&y,&z);
for(int j=x;j<=y;j++) seq[j]+=z;
}
else if(op==2)
{
ans=0;
scanf("%d%d",&x,&y);
if(x<=y)
{
for(int j=x;j<=y;j++)
{
int sell=-1e9;
for(int k=j+1;k<=y;k++)
sell=max(sell,seq[k]);
ans=max(ans,sell-seq[j]);
}
printf("%d\n",ans);
}
else
{
for(int j=x;j>=y;j--)
{
int sell=-1e9;
for(int k=j-1;k>=y;k--)
sell=max(sell,seq[k]);
ans=max(ans,sell-seq[j]);
}
printf("%d\n",ans);
}
}
// for(int i=1;i<=n;i++) printf("%d ",seq[i]);
// printf("\n");
}
} int ask_max(int l,int r)
{
int k=log2(r-l+1);
return max(sta[l][k],sta[r-(1<<k)+1][k]);
} int main()
{
// freopen("wuliangye.in","r",stdin);
// freopen("wuliangye.out","w",stdout);
scanf("%d%d",&n,&m);
if(n<=500&&m<=500) {subtask1();return 0;}
for(int i=1;i<=n;i++) scanf("%d",&sta[i][0]);
for(int j=1;j<=30;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
sta[i][j]=max(sta[i][j-1],sta[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++)
{
int op=0,l=0,r=0;
scanf("%d",&op);
if(op==2)
{
ans=0;
scanf("%d%d",&l,&r);
if(l<=r)
{
for(int j=l;j<=r-1;j++)
ans=max(ans,ask_max(j+1,r)-sta[j][0]);
}
else
{
for(int j=l;j>=r+1;j--)
ans=max(ans,ask_max(r,j-1)-sta[j][0]);
}
printf("%d\n",ans);
}
}
return 0;
}

正解:的确是线段树,答案是需要这样维护,对于一个\(l<r\)的区间,答案是这样更新的:左区间的答案、右区间的答案、跨区间的情况。而跨区间的情况即右儿子的最大值减左儿子的最小值。普通区间维护就行了,因为有两种走法(从左到右,从右到左),那么需要记录两种答案,和区间最大值最小值。

#include<cstdio>
#include<algorithm>
#define maxn 100090 using namespace std;
typedef long long ll; int n,m;
int val[maxn];
struct Segmenttree{
int l,r;
int lazy,maxx,minn,ans1,ans2;
}t[maxn*4]; void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].maxx=t[p].minn=val[l];
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p].maxx=max(t[p<<1].maxx,t[p<<1|1].maxx);
t[p].minn=min(t[p<<1].minn,t[p<<1|1].minn);
t[p].ans1=max(max(t[p<<1].ans1,t[p<<1|1].ans1),t[p<<1|1].maxx-t[p<<1].minn);
t[p].ans2=max(max(t[p<<1].ans2,t[p<<1|1].ans2),t[p<<1].maxx-t[p<<1|1].minn);
} void update(int p)
{
if(!t[p].lazy||t[p].l==t[p].r) return ;
t[p<<1].lazy+=t[p].lazy;
t[p<<1|1].lazy+=t[p].lazy;
t[p<<1].maxx+=t[p].lazy;
t[p<<1].minn+=t[p].lazy;
t[p<<1|1].maxx+=t[p].lazy;
t[p<<1|1].minn+=t[p].lazy;
t[p].lazy=0;
} void change(int p,int l,int r,int k)
{
update(p);
if(t[p].l==l&&t[p].r==r)
{
t[p].maxx+=k;
t[p].minn+=k;
t[p].lazy+=k;
return ;
}
int mid=(t[p].l+t[p].r)>>1;
if(l>mid) change(p<<1|1,l,r,k);
else if(r<=mid) change(p<<1,l,r,k);
else change(p<<1,l,mid,k),change(p<<1|1,mid+1,r,k);
t[p].maxx=max(t[p<<1].maxx,t[p<<1|1].maxx);
t[p].minn=min(t[p<<1].minn,t[p<<1|1].minn);
t[p].ans1=max(max(t[p<<1].ans1,t[p<<1|1].ans1),t[p<<1|1].maxx-t[p<<1].minn);
t[p].ans2=max(max(t[p<<1].ans2,t[p<<1|1].ans2),t[p<<1].maxx-t[p<<1|1].minn);
} int query_MAX(int p,int l,int r)
{
update(p);
if(t[p].l==l&&t[p].r==r) return t[p].maxx;
int mid=(t[p].l+t[p].r)>>1;
if(l>mid) return query_MAX(p<<1|1,l,r);
else if(r<=mid) return query_MAX(p<<1,l,r);
else return max(query_MAX(p<<1,l,mid),query_MAX(p<<1|1,mid+1,r));
} int query_MIN(int p,int l,int r)
{
update(p);
if(t[p].l==l&&t[p].r==r) return t[p].minn;
int mid=(t[p].l+t[p].r)>>1;
if(l>mid) return query_MIN(p<<1|1,l,r);
else if(r<=mid) return query_MIN(p<<1,l,r);
else return min(query_MIN(p<<1,l,mid),query_MIN(p<<1|1,mid+1,r));
} int ask1(int p,int l,int r)
{
update(p);
if(t[p].l==l&&t[p].r==r) return t[p].ans1;
int mid=(t[p].l+t[p].r)>>1;
if(l>mid) return ask1(p<<1|1,l,r);
else if(r<=mid) return ask1(p<<1,l,r);
else return max(max(ask1(p<<1,l,mid),ask1(p<<1|1,mid+1,r)),query_MAX(p<<1|1,mid+1,r)-query_MIN(p<<1,l,mid));
} int ask2(int p,int l,int r)
{
update(p);
if(t[p].l==l&&t[p].r==r) return t[p].ans2;
int mid=(t[p].l+t[p].r)>>1;
if(l>mid) return ask2(p<<1|1,l,r);
else if(r<=mid) return ask2(p<<1,l,r);
else return max(max(ask2(p<<1,l,mid),ask2(p<<1|1,mid+1,r)),query_MAX(p<<1,l,mid)-query_MIN(p<<1|1,mid+1,r));
} int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int opt=0,l=0,r=0,w=0;
scanf("%d",&opt);
if(opt==1) scanf("%d%d%d",&l,&r,&w),change(1,l,r,w);
else if(opt==2)
{
scanf("%d%d",&l,&r);
if(l==r) printf("0\n");
else if(l<r) printf("%d\n",ask1(1,l,r));
else if(l>r) printf("%d\n",ask2(1,r,l));
}
}
return 0;
}

这题...还是比较简单的啊(!),考场上码一半放弃了...再写写应该是可以对的啊。线段树这种用左儿子+右儿子+左右儿子交界来更新答案的这种思想应该很常见了啊,还是没熟练用上。

五粮液【线段树】By cellur925的更多相关文章

  1. Luogu P1637 三元上升子序列【权值线段树】By cellur925

    题目传送门 emmm..不开结构体的线段树真香! 首先我们知道"三元上升子序列"的个数就是对于序列中的每个数,**它左边比他小的数*它右边比他大的数**.但是如何快速求出这两个数? ...

  2. Luogu P1438无聊的序列【线段树/差分】By cellur925

    题目传送门 题目大意:维护一个序列,维护区间加等差数列,单点查询的操作. 首先我们肯定是要用线段树来维护了,按照一般的思维局限,我选择了维护序列中的值,但是区间修改的时候由于公差的存在,所以区间修改有 ...

  3. Luogu P1607 庙会班车【线段树】By cellur925

    题目传送门 据说可以用贪心做?算了算了...我都不会贪.... 开始想的是用线段树,先建出一颗空树,然后输进区间操作后就维护最大值,显然开始我忽视了班车的容量以及可以有多组奶牛坐在一起的信息. 我们肯 ...

  4. 浅谈线段树 (例题:[USACO08FEB]酒店Hotel)By cellur925

    今天我们说说线段树. 我个人还是非常欣赏这种数据结构的.(逃)因为它足够优美,有递归结构,有左子树和右子树,还有二分的思想. emm这个文章打算自用,就不写那些基本的操作了... 1° 简单的懒标记( ...

  5. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  6. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  7. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  8. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  9. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

随机推荐

  1. 九度OJ 1140:八皇后 (八皇后问题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:795 解决:494 题目描述: 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * ...

  2. 九度OJ 1136:Number Steps(步数) (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:691 解决:412 题目描述: Starting from point (0,0) on a plane, we have written ...

  3. 清理yum 缓存

    两条命令 yum clean all 以及 rm -rf /var/cache/yum/* 如何有效的清理yum缓存 - CSDN博客 https://blog.csdn.net/nsrainbow/ ...

  4. Node 文件上传,ZIP

    上传文件: 很多人会使用第三包进行文件的上传,例如formidable. 我也研究过,可是与Express3.x框架一起使用时,发现上传的文件总是找不到.结果原因是下面这句导致: app.use(ex ...

  5. Vue源码探究-状态初始化

    Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...

  6. Alsa中PCM参数设置⭐⭐

    1) PCM设备的句柄.2) 指定同时可供回放或截获的PCM流的方向3) 提供一些关于我们想要使用的设置选项的信息,比如缓冲区大小,采样率,PCM数据格式等4) 检查硬件是否支持设置选项.   4.1 ...

  7. Oracle 数据库基础 出现invalid username/password; logon denied错误解决方案

    出现invalid username/password; logon denied错误解决方案 [win7或win8中 cmd要以管理员身份运行] 1.Dos下输入命令:sqlplus sys/安装时 ...

  8. 【mysql】mysql innodb 配置详解

    MySQL innodb 配置详解 innodb_buffer_pool_size:这是InnoDB最重要的设置,对InnoDB性能有决定性的影响.默认的设置只有8M,所以默认的数据库设置下面Inno ...

  9. 调用html进行android布局

    1. [代码]html代码     <html>  <head>    <meta http-equiv="content-type" content ...

  10. github如何提交自己修改的代码

    当在github上发现别人项目有BUG,或者想要完善其功能的时候,该如何把自己的修改提交到项目中呢? 以logback为例 步骤: 1, fork一份logback代码到自己的仓库 进入github要 ...