集訓的時候考這道題,現場做到這道題時沒什麼思路,過幾天重看之後,還是沒什麼思路,然後上網搜了一下,發現用的是單調隊列,趕緊補了一下單調隊列的知識,接着又看了一下這道題,想了一會,好像有一點明白了。在此記下這道有意思的題。
題目大意:有n個被編了號的人,如果左邊的人的編號比右邊的人的編號大,則左邊的人可以殺了右邊的人,注意,人可以同時被殺。題目描述比較簡單,容易看懂這裏就不再贅述了。附鏈接http://codeforces.com/problemset/problem/319/B。
大體思路:開闢一個數組num[100005]用於記錄各個編號所對應的人被殺的順序(即第幾輪被殺),如果編號爲 i 的人第一輪就被殺,則num[i]=1,當然,沒被殺num[i]=0,再用一個 vector 數組維持單調遞減的隊列,它的作用在於,如果輸入一個數比隊列裏的最後一個數大,說明輸入的這個數被殺的順序在隊列最後一個之後,然後彈出最後一個數,繼續向前比較,這就是單調隊列在這裏的用處。當然我不知道是否還有其它思路,也許可以不用單調隊列。
下面是ac代碼:
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int num[100005];
vector<int> v;
int main(){
int n;
while(cin>>n){
int a;
v.clear();
memset(num,0,sizeof(num));
for(int i=0;i<n;i++){
cin>>a;
int cnt=0; //記錄編號爲i的人在第幾輪被殺
if(v.empty())
v.push_back(a);
else{
while(v.back()<a){
cnt=max(cnt,num[v.back()]);
v.pop_back();
if(v.empty())
break;
}
if(v.empty())
v.push_back(a);
else{
num[a]=cnt+1;
v.push_back(a);
}
}
}
int maxn=0;
for(int i=0;i<n;i++)
maxn=max(maxn,num[i]);
cout<<maxn<<endl;
}
return 0;
}