https://www.acmicpc.net/problem/3015
* 풀이
- stack은 그림을 그려놓고 <--- 방향으로 하나씩 탐색하면된다.
- 크게 3가지경우로 생각하라.
- 오름차순
- 나보다 작은것들과 1쌍, pop
- 내림차순
- 위에서 나보다 작은것은 걸러졌음, stack에 원소가 있다면, 무조건 나보다 큰것이 보장.
- 나보다 큰애와 1쌍을 이룬다.
- 같은경우를 추가로 생각해야한다.
- pop은 하되, cnt(//현재 사람의 연속 카운트)를 저장해놓는 idea
- 같은거 뒤에 작은게옴 -> 정답 1쌍 추가 (위와동일) , cnt=1로 리셋
- 같은거 뒤에 큰게옴 -> 이전 막대기의 cnt를 더해줘야함, cnt=1로 리셋
- 같은거 뒤에 같은게옴 -> 현재cnt를 이전 막대기의 cnt +1로 갱신, 스택에넣기
- cnt 시작을 1로하고, 오름차순일때 ret+1 하는대신 ret+직전cnt 하면 일반화 된다.
- long long을 써야하는이유
- 50만개의 모두 같은키가 오는경우 때문
* 최종코드
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, ret, arr[500000+4];
// < 키, 연속된 같은키 카운팅 >
stack<pair<ll,ll>> stk; // 최악 50만개 다같은키인경우) n(n-1)/2
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>n;
for(int i=0;i<n;++i) {
cin>>arr[i];
}
for(int i=0;i<n;++i) {
int cnt=1; //현재 사람의 연속 카운트 초기값 = 1
// 오름차순인경우
while(stk.size() && stk.top().first <= arr[i]) {
ret+=stk.top().second; // 누적된 카운트들 더하기
//같은경우 카운팅해주기
if(stk.top().first == arr[i]) {
cnt = stk.top().second+1;
}
else {
cnt=1; // 다른키인경우 카운트 리셋
}
stk.pop();
}
// 내림차순인경우, 나보다 더큰사람이 있다는뜻 -> 1쌍추가
if(stk.size()) ret++;
stk.push({arr[i],cnt});
}
cout<<ret;
return 0;
}
'Algorithm > 스택' 카테고리의 다른 글
[알고리즘] 백준 6549 히스토그램 // 스택 심화, 암기.. (0) | 2025.01.19 |
---|---|
[알고리즘] 백준 15926 현욱은 괄호왕이야 // stack, 괄호검사 심화 (0) | 2025.01.19 |
[알고리즘] 백준 1725 히스토그램 // 스택 (0) | 2024.12.29 |
[알고리즘] 백준 6198 옥상정원꾸미기 // 스택, 역발상, 자기중심적 사고, st.size() 도 의미가 있다. (0) | 2024.12.29 |
[알고리즘] 백준 17299 오등큰수 // 스택 (0) | 2024.12.28 |