Passing the Message
阿新 • • 發佈:2021-08-09
Passing the Message-HDU3410
題目連結: [](Problem - 3410 (hdu.edu.cn))
小難啊這題....
$2^8$
題目大意:
輸出每一個位置的人向左/右看,看到的比他矮的最高的人的下標。(每個同學的身高不一樣)如果有人比他高那就看不到那個比他高的人後面了(視野會被擋住)
思路:
只要解決向右看,向左看就迎刃而解了,只是方向不一樣。
對於每一個位置i,只記錄[i+1,n]中的最大值是不夠的,因為很有可能最大值所在位置和i之間有符合比i矮的最大的這一條件位置。
需要維護一個棧頂到棧底遞增的單調棧來記錄i後面的情況。舉個例子,如果i位後是4 3 5,這個3是多餘的,因為i位無非兩種情況:1. i<=4 那麼i根本看不到3;2. i>4 那麼i雖然可以看到3,但是找最大值是輪不到這個3的(有4,5在)
例子:
因為向右邊看要得出準確答案需要右邊的區間提前處理完畢,所以向右邊看就是從後往前遍歷,反之則從前往後遍歷。
總的來說,要維護一個範圍為[i+1,n]的單調棧(棧頂到棧低單調遞增),供i往後面找符合條件的值,並且在找的過程中,通過彈棧保持單調性。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define drep(i,a,b) for(int i=b;i>=a;i--) using namespace std; const int N = 5*1e5+50; int T,n,cas; struct kid{ int h,idx; }a[N]; int ansl[N],ansr[N]; void solve(){ stack<kid>st; drep(i,1,n){ while(st.size() && st.top().h<=a[i].h){ if(st.top().h != a[i].h)ansr[i]=st.top().idx; st.pop(); }st.push(a[i]); } stack<kid>sk; rep(i,1,n){ while(sk.size() && sk.top().h<=a[i].h){ if(sk.top().h != a[i].h)ansl[i]=sk.top().idx; sk.pop(); }sk.push(a[i]); } printf("Case %d:\n",++cas); rep(i,1,n)printf("%d %d\n",ansl[i],ansr[i]); } int main(){ scanf("%d",&T); while(T--){ memset(ansr,0,sizeof ansr); memset(ansl,0,sizeof ansl); scanf("%d",&n); a[n+1].h=a[n+1].idx=0; rep(i,1,n){ scanf("%d",&a[i].h); a[i].idx=i; } solve(); } }