- メッセージを渡す
- 質問の意味
一連の番号が与えられた場合、各番号の左(および右)の連続して小さい番号で最大の番号の位置を見つけます。
- アイデア
まず、左側の連続する小さい番号の中から最大の番号の位置を見つける方法を考えてみましょう。これは、単純なデータ構造(単調なスタック)を使用します。
単調なスタック:単調なスタックは実際にはスタックですが、いくつかを使用します。巧妙なロジックにより、新しい要素がスタックにプッシュされるたびに、スタック内の要素が順番に(単調に増加または単調に減少)維持されます。ここでは、単調に減少するスタックを使用します(つまり、スタックの下部から上部への添え字が増加します)。はい、ただしデータは減少しています)ちなみに、スタックは単調に増加しています(下付き文字はスタックの一番下から一番上に向かって増加していますが、データも増加しています)。
原則として、コードを読んだ後、じっくり味わうことができます〜
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<ll,ll> pa;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int MAX_N=5e4+7;
int T,N;
int hei[MAX_N],resl[MAX_N],resr[MAX_N];
stack<int>S;
int main()
{
ios::sync_with_stdio(false);
cin>>T;
int i,j,k=0;
while(T--){
cin>>N;
for(i=1;i<=N;i++){
cin>>hei[i];
}
while(!S.empty())
S.pop();
for(i=1;i<=N;i++){
resl[i]=0;
while(!S.empty()&&hei[S.top()]<hei[i]){
resl[i]=S.top();
S.pop();
}
S.push(i);
}
while(!S.empty())
S.pop();
for(i=N;i;i--){
resr[i]=0;
while(!S.empty()&&hei[S.top()]<hei[i]){
resr[i]=S.top();
S.pop();
}
S.push(i);
}
cout<<"Case "<<++k<<":"<<endl;
for(i=1;i<=N;i++){
cout<<resl[i]<<' '<<resr[i]<<endl;
}
}
return 0;
}