2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)
题意:求一个序列的最大的(区间最小值*区间和)
线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum、最小前缀lsum、最小后缀rsum,枚举每个数a[i],设以a[i]为最小值的区间为[l,r]
若a[i]>0,则最优解就是a[i]*([l,r]的区间和),因为[l,r]上的数都比a[i]大。
若a[i]<0,则最优解是a[i]*([l,i-1]上的最小后缀+a[i]+[i+1,r]上的最小前缀),在线段树上查询即可。
复杂度$O(nlogn)$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+,inf=0x3f3f3f3f;
int a[N],n,sta[N],L[N],R[N],tp;
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
struct D {ll sum,lsum,rsum;} s[N<<];
D mg(D a,D b) {
D t= {,};
t.sum=a.sum+b.sum;
t.lsum=min(a.lsum,a.sum+b.lsum);
t.rsum=min(b.rsum,b.sum+a.rsum);
return t;
}
void build(int u=,int l=,int r=n) {
if(l==r) {s[u].sum=a[l],s[u].lsum=min((ll)a[l],0ll),s[u].rsum=min((ll)a[l],0ll); return;}
build(ls,l,mid),build(rs,mid+,r),s[u]=mg(s[ls],s[rs]);
}
void qry(int L,int R,D& x,int u=,int l=,int r=n) {
if(l>=L&&r<=R) {x=mg(x,s[u]); return;}
if(l>R||r<L)return;
qry(L,R,x,ls,l,mid),qry(L,R,x,rs,mid+,r);
}
int main() {
scanf("%d",&n);
a[]=a[n+]=~inf;
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
sta[tp=]=;
for(int i=; i<=n; ++i) {
for(; a[sta[tp]]>=a[i]; --tp);
L[i]=sta[tp]+,sta[++tp]=i;
}
sta[tp=]=n+;
for(int i=n; i>=; --i) {
for(; a[sta[tp]]>=a[i]; --tp);
R[i]=sta[tp]-,sta[++tp]=i;
}
build();
ll ans=;
for(int i=; i<=n; ++i) {
if(a[i]>) {
D t= {,};
qry(L[i],R[i],t);
ans=max(ans,a[i]*t.sum);
} else if(a[i]<) {
ll x=;
D t= {,};
qry(L[i],i,t);
x+=t.rsum;
t= {,};
qry(i,R[i],t);
x+=t.lsum;
x-=a[i];
ans=max(ans,a[i]*x);
}
}
printf("%lld\n",ans);
return ;
}
笛卡尔树做法:对整个序列建立笛卡尔树,用和线段树相同的方法求出每个结点的子树所代表区间的sum,lsum,rsum,枚举每个结点,如果是正数则乘上该结点的sum,如果是负数则乘上该结点的(左儿子的rsum+右儿子的lsum+结点本身的值)即可。
复杂度$O(n)$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+,inf=0x3f3f3f3f;
int n,a[N],ls[N],rs[N],sta[N],tp;
ll sum[N],lsum[N],rsum[N];
void build() {
a[n+]=~inf,sta[tp=]=n+;
for(int i=; i<=n; ++i) {
for(; a[i]<a[sta[tp]]; --tp);
ls[i]=rs[sta[tp]],rs[sta[tp]]=i,sta[++tp]=i;
}
}
void dfs(int u) {
if(!u)return;
dfs(ls[u]),dfs(rs[u]);
sum[u]=sum[ls[u]]+a[u]+sum[rs[u]];
lsum[u]=min(lsum[ls[u]],sum[ls[u]]+a[u]+lsum[rs[u]]);
rsum[u]=min(rsum[rs[u]],sum[rs[u]]+a[u]+rsum[ls[u]]);
}
int main() {
scanf("%d",&n);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
build(),dfs(rs[n+]);
ll ans=;
for(int i=; i<=n; ++i) {
if(a[i]>)ans=max(ans,a[i]*sum[i]);
else if(a[i]<)ans=max(ans,a[i]*(rsum[ls[i]]+a[i]+lsum[rs[i]]));
}
printf("%lld\n",ans);
return ;
}
2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)的更多相关文章
- 计蒜客 38228. Max answer-线段树维护单调栈(The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer 南昌邀请赛网络赛) 2019ICPC南昌邀请赛网络赛
Max answer Alice has a magic array. She suggests that the value of a interval is equal to the sum of ...
- 南昌邀请赛I.Max answer 单调栈+线段树
题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ...
- 网络赛 I题 Max answer 单调栈+线段树
题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...
- The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)
题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...
- 2019南昌邀请赛网络预选赛 I. Max answer(单调栈+暴力??)
传送门 题意: 给你你一序列 a,共 n 个元素,求最大的F(l,r): F(l,r) = (a[l]+a[l+1]+.....+a[r])*min(l,r); ([l,r]的区间和*区间最小值,F( ...
- 南昌邀请赛网络赛 D.Match Stick Game(dp)
南昌邀请赛网络赛 D.Match Stick Game 题目传送门 题目就会给你一个长度为n的字符串,其中\(1<n<100\).这个字符串是一个表达式,只有加减运算符,然后输入的每一个字 ...
- icpc 南昌邀请赛网络赛 Max answer
就是求区间和与区间最小值的积的最大值 但是a[i]可能是负的 这就很坑 赛后看了好多dalao的博客 终于a了 这个问题我感觉可以分为两个步骤 第一步是对于每个元素 以它为最小值的最大区间是什么 第二 ...
- 南昌网络赛 I. Max answer 单调栈
Max answer 题目链接 https://nanti.jisuanke.com/t/38228 Describe Alice has a magic array. She suggests th ...
- 南昌网络赛 I. Max answer (单调栈 + 线段树)
https://nanti.jisuanke.com/t/38228 题意给你一个序列,对于每个连续子区间,有一个价值,等与这个区间和×区间最小值,求所有子区间的最大价值是多少. 分析:我们先用单调栈 ...
随机推荐
- Struts2的select使用
struts2的select标签中,常用的有以下几个属性:(1)struts2中的select 标签中,必须设置的属性只有一个,即是list.(2)select标签的list中必须有值,不然会报错.如 ...
- Eclipse关联JDK源码
1. http://blog.csdn.net/weiwangchao_/article/details/25960961 2. 1.点 "window">"Pre ...
- MVVM模式的3种command总结[1]--DelegateCommand
MVVM模式的3种command总结[1]--DelegateCommand 查了不少资料,大概理清楚的就是有3种.当然类名可以自己取了,不过为了便于记忆和区分,还是和看到的文章里面用一样的类名. 1 ...
- 4.彻底理解synchronized
1. synchronized简介 在学习知识前,我们先来看一个现象: public class SynchronizedDemo implements Runnable { private s ...
- 第八天 1-7 实战:创建一个root无法删除的文件
实战:创建一个root无法删除的文件 简介:Linux文件的最底层(内核级别)属性的查看与修改 命令:lsattr.chattr Linux文件除了具有基本权限rwx,及特殊权限(SUID.SGID. ...
- nyoj520——素数序列
最大素因子 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 GreyAnts最近正在学习数论中的素数,但是现在他遇到了一个难题:给定一个整数n,要求我们求出n的最大素 ...
- EasyUI validType属性
/** * 包含easyui的扩展和常用的方法 * * @author * * @version 20120806 */ var wjc = $.extend({}, wjc);/* 定义全局对象,类 ...
- 010——数组(十)compact extract in_array
<?php /** 10 数组 compact extract in_array */ //compact() (紧凑的,简洁的) 将变量转换为数组,变量名为数组键名,变量值为数组的键值. /* ...
- 分布式锁-基于ZK和Redis实现
一.基于zookeeper实现分布式锁 1.1 Zookeeper的常用接口 package register; import java.util.List; import java.util.con ...
- SpringInAction--Bean参数的自动注入
前面我已经学过了,将一个bean引用注入到另一个bean的属性或构造器参数中,这边指的是将一个对象与另一个对象进行关联. 我们学过的方法是在创建的时候根据new对象的时候,注入参数,如下: @Bean ...