五粮液【线段树】By cellur925
考场上感觉的确是线段树,还要维护区间最值...最值怎么维护?还要区间修改?\(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的更多相关文章
- Luogu P1637 三元上升子序列【权值线段树】By cellur925
题目传送门 emmm..不开结构体的线段树真香! 首先我们知道"三元上升子序列"的个数就是对于序列中的每个数,**它左边比他小的数*它右边比他大的数**.但是如何快速求出这两个数? ...
- Luogu P1438无聊的序列【线段树/差分】By cellur925
题目传送门 题目大意:维护一个序列,维护区间加等差数列,单点查询的操作. 首先我们肯定是要用线段树来维护了,按照一般的思维局限,我选择了维护序列中的值,但是区间修改的时候由于公差的存在,所以区间修改有 ...
- Luogu P1607 庙会班车【线段树】By cellur925
题目传送门 据说可以用贪心做?算了算了...我都不会贪.... 开始想的是用线段树,先建出一颗空树,然后输进区间操作后就维护最大值,显然开始我忽视了班车的容量以及可以有多组奶牛坐在一起的信息. 我们肯 ...
- 浅谈线段树 (例题:[USACO08FEB]酒店Hotel)By cellur925
今天我们说说线段树. 我个人还是非常欣赏这种数据结构的.(逃)因为它足够优美,有递归结构,有左子树和右子树,还有二分的思想. emm这个文章打算自用,就不写那些基本的操作了... 1° 简单的懒标记( ...
- 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是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
随机推荐
- c#4.5新语法--自动属性和隐式类型
1.自动属性 自动属性是c#中属性定义的两种形式的一种:传统属性定义.自动属性. 1.1 传统属性定义 private int _age; public int ...
- 有返回值的Bookmark
首先代码创建Activity: public sealed class WaitForResponse<TResult>:NativeActivity<TResult> { p ...
- appium()-java-client-api
//appium java-client-api 介绍 原文地址:http://appium.github.io/java-client/index-all.html#_S_ A B C D E F ...
- UITextInputMode类的使用
转载请注明:http://blog.sina.com.cn/s/blog_69081e060100v7ad.html UITextInputMode大家看了是不是有些陌生呢?这个类是在4.2之后才 ...
- Go语言string,int,int64 ,float之间类型转换方法
(1)int转string ? 1 2 s := strconv.Itoa(i) 等价于s := strconv.FormatInt(int64(i), 10) (2)int64转string ? 1 ...
- 网站流量统计之PV和UV
转自:http://blog.csdn.NET/webdesman/article/details/4062069 如果您是一个站长,或是一个SEO,您一定对于网站统计系统不会陌生,对于SEO新手来说 ...
- fatal error C1902: 程序数据库管理器不匹配;请检查安装解决
http://blog.sina.com.cn/s/blog_9f4bc8e301015uhz.html 1.错误提示:VS2008编译错误fatal error C1902: 程序数据库管理器不匹配 ...
- Java网络编程InetAddress类
InetAddress用来代表IP地址.一个InetAdress的对象就代表着一个IP地址, getByName(String host):在给定主机名的情况下确定主机的 IP 地址,主机名可以是机器 ...
- CISCO-端口安全
1.MAC地址与端口绑定,当发现主机的MAC地址与交换机上指定的MAC地址不同时 ,交换机相应的端口将down掉.当给端口指定MAC地址时,端口模式必须为access或者Trunk状况. 3550-1 ...
- Opencv— — Pinch Filter
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...