概述
- 题目: 区间最大值
- 思路: (看别人的题解 单调栈 + 倍增 + 前缀) 因为学习倍增还是还是关于树上倍增导致思维僵硬,对于倍增算法的其他类型应用就不会融会贯通 这道题很好的锻炼了我这一方面的缺陷
首先是两个数组 fa[i][j]来记录下标 i 向右走 2 j的最大值所在的段
dis[i][j]记录下标 i 向右走 2 j的所做的贡献
先来一个单调栈来预处理一下所有的 fa[i][0] dis[i][0],然后再进行倍增算法,处理结束以后读入查询 最后一段再额外加上去
代码:
#include <bits/stdc++.h>
#define int long long
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int>
using namespace std;
const int N = 2e5 + 100,M = N * 2,INF = 0x3f3f3f3f;
int a[N],s[N];
stack<int> d;
int fa[N][20],dis[N][20];
void solve()
{
int n,q; cin >> n >> q;
for(int i = 1;i <= n;i ++ ) cin >> a[i],s[i] = s[i - 1] + a[i];
for(int i = n;i >= 1;i -- )
{
while(d.size() && a[d.top()] < a[i]) d.pop();
if(!d.size()) fa[i][0] = n + 1;
else fa[i][0] = d.top();
d.push(i);
}
for(int i = 1;i <= n;i ++ )
{
int vis = s[fa[i][0] - 1] - s[i - 1];
dis[i][0] = a[i] * vis;
}
for(int j = 1;j <= 19;j ++ )
{
for(int i = 1;i <= n;i ++ )
{
fa[i][j] = fa[fa[i][j - 1]][j - 1];
dis[i][j] = dis[i][j - 1] + dis[fa[i][j - 1]][j - 1];
}
}
while(q -- )
{
int l,r; cin >> l >> r;
int p = l;
int ans = 0;
for(int i = 19;i >= 0;i -- )
{
if(fa[p][i] <= r && fa[p][i])
{
ans += dis[p][i];
p = fa[p][i];
}
}
ans += a[p] * (s[r] - s[p - 1]);
cout << ans << endl;
}
}
signed main()
{
ios;int T = 1; while(T -- ) solve();
return 0;
}
``
最后
以上就是隐形黑猫为你收集整理的百度之星初赛第三场6的全部内容,希望文章能够帮你解决百度之星初赛第三场6所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复