2019南昌网络赛-I(单调栈+线段树)
题目链接:https://nanti.jisuanke.com/t/38228
题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值。
思路:比赛时还不会线段树,和队友在这题上弄了3小时,思路大体都是对的,但就是没法实现。这几天恶补线段树。
首先可以利用单调栈来查找满足a[i]为最小值的最大区间L[i]~R[i]。然后利用线段树求一个段的和sum、最小前缀lsum和最小后缀rsum。然后遍历a[i]:
a[i]>0:最优为sum(L[i],R[i])*a[i]
a[i]<0:最优为(sumr(L[i],i)+suml(i,R[i]-i)*a[i]
这里用线段树查询可以用传递引用来求lsum和rsum,因为我们查询一段区间是从左向右查询的,或者可以用三个全局变量Sum、Lsum、Rsum记录当前已找到的区间的对应属性也行。
AC代码:
#include<cstdio> #include<algorithm> using namespace std; const int maxn=500005; typedef long long LL;struct node{int l,r;LL sum,lsum,rsum; //sum为区间和,lsum最小前缀,rsum最小后缀 }tr[maxn<<2]; //L[i]~R[i]为满足a[i]为最小的最大区间 int n,p,a[maxn],L[maxn],R[maxn],stk[maxn]; LL ans;node gets(node a,node b){node t;t.l=a.l,t.r=b.r;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 v,int l,int r){tr[v].l=l,tr[v].r=r;if(l==r){tr[v].sum=a[r];tr[v].lsum=min(a[r]*1LL,0LL);tr[v].rsum=min(a[r]*1LL,0LL);return;}int mid=(l+r)>>1;build(v<<1,l,mid);build(v<<1|1,mid+1,r);tr[v]=gets(tr[v<<1],tr[v<<1|1]); }void query(node &x,int v,int l,int r){if(l<=tr[v].l&&r>=tr[v].r){x=gets(x,tr[v]);return;}int mid=(tr[v].l+tr[v].r)>>1;if(l<=mid) query(x,v<<1,l,r);if(r>mid) query(x,v<<1|1,l,r); }int main(){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&a[i]);a[0]=a[n+1]=0xcfcfcfcf;stk[p=0]=0; //利用单调栈求L[i],R[i]for(int i=1;i<=n;++i){while(a[stk[p]]>=a[i]) --p;L[i]=stk[p]+1;stk[++p]=i;}stk[p=0]=n+1;for(int i=n;i>=1;--i){while(a[stk[p]]>=a[i]) --p;R[i]=stk[p]-1;stk[++p]=i;}build(1,1,n);for(int i=1;i<=n;++i){if(a[i]>0){node t;t.sum=t.lsum=t.rsum=0;query(t,1,L[i],R[i]);if(a[i]*t.sum>ans) ans=a[i]*t.sum;}else if(a[i]<0){LL tmp=0;node t;t.sum=t.lsum=t.rsum=0;query(t,1,L[i],i);tmp+=t.rsum;t.sum=t.lsum=t.rsum=0;query(t,1,i,R[i]);tmp+=t.lsum;tmp-=a[i];if(tmp*a[i]>ans) ans=tmp*a[i];}}printf("%lld\n",ans);return 0; }
转载于:https://www.cnblogs.com/FrankChen831X/p/10784963.html
2019南昌网络赛-I(单调栈+线段树)相关推荐
- [CF 526 F] Pudding Monsters(单调栈 + 线段树)
CF526F Pudding Monsters problem solution code problem luogu翻译 solution observation :每行每列恰好有一个棋子,所以如果 ...
- 2019南昌网络赛 I. Yukino With Subinterval 树状数组套线段树
I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...
- 2019南昌网络赛 C题,Hello 2019
题意:求包含9012,但是不包含8012的最小删除次数 解题思路:首先将字符串反转,按照题解思路为线段树维护矩阵即可 我们将线段树的每个区间用矩阵表示,矩阵mat[5][5]维护2019这个序列的情况 ...
- HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线
传送门 文章目录 题意: 思路: 题意: 思路: 考虑将贡献分开来算,先计算最大值,再算个最小值,之后答案就是((max+min)/2)/(len∗(len+1)/2)((max+min)/2)/(l ...
- [LOJ3153] 三级跳(单调栈 + 线段树)
problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论: 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对,如果有一个数 i∈(x,y)∧ai≥axi ...
- 扶桑号战列舰 (单调栈+线段树区间更新懒惰标记 or 栈)
传送门 •题目描述 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当时世界上武装最为强大的舰只. ...
- [单调栈+线段树] 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest ——A. LaIS
题面$ link 定义了长度为 kkk 的几乎递增序列 {bi}\{b_i\}{bi} 为: min(b1,b2)≤min(b2,b3)≤...min(bk−1,bk)min(b_1, b_2) ...
- COCI 2015/2016 PROKLETNIK(单调栈+线段树)
COCI 2015/2016 PROKLETNIK 题目大意 给定序列A1..NA_{1..N}A1..N,分别求出QQQ组询问区间[L,R][L,R][L,R]中最长的连续子序列Al..rA_{l ...
- L. Continuous Intervals(单调栈 + 线段树 + 思维)
L. Continuous Intervals 给定一个长度为nnn的数组,问里面有多少个区间[l,r][l, r][l,r],满足,对这个区间排序后,两两差值$ \leq 1$,输出区间个数. 如果 ...
最新文章
- 公交车下发现一具男尸
- arduino 中断例程
- Paypal IPN
- Oracle-awrddrpt.sql比较两个AWR差异报告
- 201771010118马昕璐《面向对象程序设计java》第八周学习总结
- solr analyzer_查看您的Solr缓存大小:Eclipse Memory Analyzer
- 前端学习(1330):数据库相关概念
- php怎么查询数据库,php怎么查询数据库
- vue中Axios网络请求之Vue知识点归纳(十)
- @vail 判断某字段在范围内_条件判断函数If,你真的会使用吗?实用技巧都掌握吗?...
- 在阿里云上试用 Knative 1
- C语言以科学计数法的格式打印
- C语言基础之十进制与二进制转换
- LLVM的源码目录结构
- python栈是什么意思_Python算法之栈(stack)的实现
- HttpWebRequest 无法连接到远程服务器
- 机器学习之k-means算法详解
- 假如易立竞吐槽程序员。。。
- 深度分析Facebook ADS广告投放平台(1):平台介绍
- 2021年终总结,程序员的日子