标签:inf turn test namespace nbsp cst str long href
题目链接:https://codeforces.com/contest/1359/problem/D
想法:
因为是减去最大值,我们可以考虑直接枚举最大值。
找到左边最后一个 小于等于a[i] 的位置,找到右边最后一个 小于等于a[i] 的位置
找到这样的一个子区间,然后我们利用ST表维护前缀和,找到左边前缀和最小,右边前缀和最大的这样的范围就好了。
#pragma GCC optimize(2) #pragma GCC optimize(3) #include <algorithm> #include <string> #include <cstring> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <cmath> #include <cstdio> #include <iomanip> #include <ctime> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #define ll long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f3f3f3f3f #define max(a, b) (a>b?a:b) #define min(a, b) (a<b?a:b) const double eps = 1e-10; const int maxn = 2e5 + 10; const int MOD = 998244353; int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; } using namespace std; int a[maxn]; int q[maxn]; int f1[maxn],f2[maxn]; int pre[maxn],maxx[maxn][20],minn[maxn][20]; void rmq(int n) { for(int i=0;i<=n;i++) minn[i][0]=maxx[i][0]=pre[i]; for(int j=1;(1<<j)<=n;j++) { for(int i=0;i+j-1<=n;i++) { maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]); minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]); } } } int q1(int l,int r) { int k=0,dis=r-l+1; while((1<<(k+1))<=dis) ++k; return max(maxx[l][k],maxx[r-(1<<k)+1][k]); } int q2(int l,int r) { int k=0,dis=r-l+1; while((1<<(k+1))<=dis) ++k; return min(minn[l][k],minn[r-(1<<k)+1][k]); } int main() { int n; scanf("%d",&n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); pre[i] = pre[i-1] + a[i]; } rmq(n); int cnt; // 右边第一个 > a[i] 的数的位置 q[1] = n + 1; cnt = 1; a[n + 1] = INF; for (int i = n; i >= 1; i--) { while (cnt && a[q[cnt]] <= a[i]) cnt--; f1[i] = q[cnt] - 1; q[++cnt] = i; } // 左边第一个 > a[i] 的数的位置 q[1] = 0; cnt = 1; a[0] = INF; for (int i = 1;i <= n;i++) { while (cnt && a[q[cnt]] <= a[i]) cnt--; f2[i] = q[cnt]; q[++cnt] = i; } // for (int i = 1;i <= n;i++) { // cout << f2[i] << " "; // } // cout << endl; int ans = 0; for (int i = 1;i <= n;i++) { int l = f2[i],r = f1[i]; int maxl = q2(l,i-1); int maxr = q1(i,r); ans = max(ans,maxr - maxl - a[i]); } printf("%d\n",ans); return 0; }
D. Yet Another Yet Another Task (ST表模版 + 单调队列)
标签:inf turn test namespace nbsp cst str long href
原文地址:https://www.cnblogs.com/-Ackerman/p/13200363.html