【習題 8-18 UVA - 1619】Feel Good
阿新 • • 發佈:2018-02-21
ifdef ans pos ack color lac top pac sta
【鏈接】 我是鏈接,點我呀:)
【題意】
在這裏輸入題意
【題解】
用單調隊列求出l[i]和r[i]
分別表示i的左邊最近的大於a[i]的數的位置以及i右邊最近的大於a[i]的數的位置。
則l[i]+1..r[i]-1就是a[i]這個數作為最小數的最大管轄區間了。
寫個前綴和就好。
然後取a[i]*區間l[i]+1..r[i]-1的和 中的最大值。
並不是special judge
多個相同區間。
取區間長度最短的區間。
如果仍有多個答案。
取左端點最小的那個區間。
(全都是0的情況要註意,直接取[1,1]就好,不能取[1..n]
【代碼】
#include <bits/stdc++.h>
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1
using namespace std;
const double pi = acos(-1);
const int dx[4 ] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 1e5;
int n,a[N+10],l[N+10],r[N+10];
LL pre[N+10];
stack<int> sta;
void solve(){
rep1(i,1,n) cin >> a[i];
pre[0] = 0;
rep1(i,1,n) pre[i] = pre[i-1]+a[i];
l[1] = 0;
while (!sta.empty()) sta.pop();
sta.push(1);
for (int i = 2;i <= n;i++){
while (!sta.empty() && a[sta.top()]>=a[i]) sta.pop();
if (sta.empty())
l[i] = 0;
else
l[i] = sta.top();
sta.push(i);
}
while (!sta.empty()) sta.pop();
sta.push(n);
r[n] = n+1;
for (int i = n-1;i >= 1;i--){
while (!sta.empty() && a[sta.top()]>=a[i]) sta.pop();
if (sta.empty())
r[i] = n+1;
else
r[i] = sta.top();
sta.push(i);
}
long long ans = -1;
int posl,posr;
rep1(i,1,n){
int ll = l[i]+1;int rr = r[i]-1;
if (a[ll]==0 && a[rr]==0){
rr = ll;
}
LL temp = 1LL*a[i]*(pre[rr]-pre[ll-1]);
if (temp>ans){
ans = temp;
posl = ll,posr = rr;
}else if (temp==ans){
if (posr-posl>rr-ll || (posr-posl==rr-ll && ll<posl)){
posl = ll,posr = rr;
}
}
}
cout<<ans<<endl;
cout<<posl<<' '<<posr<<endl;
}
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
int kase = 0;
while (cin>>n){
if (kase>0)
cout<<endl;
else
kase++;
solve();
}
return 0;
}
【習題 8-18 UVA - 1619】Feel Good