LGP2422 [] 良好的感觉 学习笔记
LGP2422 [] 良好的感觉 学习笔记
题意简述
给定一个长为
说人话就是框定一个区间,其权值定义为区间最小值乘区间和,最大化此权值并输出它。
做法解析
如果你了解极值分治和笛卡尔树,你会发现这就是经典的极值分治形式,建个笛卡尔树然后dfs一遍就没了。
代码实现
#include <bits/stdc++.h>
using namespace std;
namespace obasic{
typedef long long lolo;
template <typename _T>
void readi(_T &x){
_T k=1;x=0;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')k=-1;
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
x*=k;return;
}
template <typename _T>
void writi(_T x){
if(x<0)putchar('-'),x=-x;
if(x>9)writi(x/10);
putchar(x%10+'0');
}
template <typename _T>
void maxxer(_T &x,_T y){x=max(x,y);}
};
using namespace obasic;
const int MaxN=1e5+5;
int N;lolo A[MaxN],sum[MaxN],ans;
int stk[MaxN],ktp,ls[MaxN],rs[MaxN];
lolo dfs(int u,int l,int r){
lolo res=1ll*A[u]*(sum[r]-sum[l-1]);
if(ls[u])maxxer(res,dfs(ls[u],l,u-1));
if(rs[u])maxxer(res,dfs(rs[u],u+1,r));
return res;
}
int main(){
readi(N);
for(int i=1;i<=N;i++){
readi(A[i]);
sum[i]=sum[i-1]+A[i];
}
for(int i=1;i<=N;i++){
int k=ktp;
while(k&&A[stk[k]]>A[i])k--;
if(k)rs[stk[k]]=i;
if(k<ktp)ls[i]=stk[k+1];
stk[++k]=i,ktp=k;
}
ans=dfs(stk[1],1,N);writi(ans);
return 0;
}
反思总结
极值分治与笛卡尔树的要素:静态、要考虑所有的区间、权值为区间极值和别的什么东西结合在一起得出。在这题体现的淋漓尽致。
标签:
极值分治与笛卡尔树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】