1 条题解
-
0
自动搬运
来自洛谷,原作者为

Purslane
AFO搬运于
2025-08-24 22:46:57,当前版本为作者最后更新于2023-05-01 21:40:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Solution
一道简单题,提供一种不需要脑子的做法。
首先题目问的是 。后文称这是 和 的配对。
然后考虑如果 时,如果出现了 ,那么最终答案肯定不是 和 之后的配对,不然换 根他们配对更优。
所以对于每个数 ,它只会和第一个不比它小的数之前的一部分进行配。也就是说,用单调栈找到后面的第一个不比它小的数 ,最终 只能和 中的数配对。最优情况肯定是选中间的最大值。
那么考虑询问的时候,从 出发,每次找到下一个 。由定义, 中的数肯定比 都小,也都比 小,他们一定不会作为答案配对的前者,不然换 会更优。
所以要么用 和 之间的数配对,这个可以预处理。要么看 和后面的情况,令 。
这个过程可以看做每个 向 连边然后找树链的最大值。可以倍增解决。
复杂度 。
代码:
#include<bits/stdc++.h> #define int long long #define ffor(i,a,b) for(int i=(a);i<=(b);i++) #define roff(i,a,b) for(int i=(a);i>=(b);i--) using namespace std; const int MAXN=2e5+10; int n,nxt[MAXN][30],mx[MAXN][30],st[MAXN][30],a[MAXN],q; stack<int> sts; int calc(int l,int r) {if(l>r) return 0;int k=log2(r-l+1);return max(st[l][k],st[r-(1<<k)+1][k]);} signed main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n; ffor(i,1,n) cin>>a[i],st[i][0]=a[i]; ffor(k,1,20) for(int l=1,r=(1<<k);r<=n;l++,r++) st[l][k]=max(st[l][k-1],st[l+(1<<k-1)][k-1]); a[n+1]=INT_MAX; sts.push(n+1); ffor(i,0,21) nxt[n+1][i]=n+1; roff(i,n,1) { while(a[sts.top()]<a[i]) sts.pop(); nxt[i][0]=sts.top(),mx[i][0]=a[i]*calc(i+1,nxt[i][0]-1); ffor(j,1,20) nxt[i][j]=nxt[nxt[i][j-1]][j-1],mx[i][j]=max(mx[i][j-1],mx[nxt[i][j-1]][j-1]); sts.push(i); } cin>>q; ffor(i,1,q) { int l,r; cin>>l>>r; int ans=0; roff(j,20,0) if(nxt[l][j]<=r) ans=max(ans,mx[l][j]),l=nxt[l][j]; ans=max(ans,a[l]*calc(l+1,r)); cout<<ans<<'\n'; } return 0; }
- 1
信息
- ID
- 8649
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者