티스토리 뷰
[CF 1136D] Nastya Is Buying Lunch - 1800
문제 설명 :
n명이 줄을 서 있고 문제의 주인공은 줄의 맨 뒤(n번째 인덱스)에 서 있다. 그리고 m개의 정보가 들어오는데 각 정보는 두 정수 a,b로 이루어져있다. 이 의미는 줄의 앞사람이 a번 사람이고 뒷사람이 b번 사람이라면 a와 b가 서로 자리를 바꿀 수 있다는 의미이다. 이 정보들을 바탕으로 n번째 사람은 최대 몇 칸이나 앞으로 움직일 수 있는지 구하는 문제이다.
풀이 :
이 문제에서 관심이 있는 것은 맨 뒷사람(편의상 last라고 두자)이 최대 몇 칸이나 앞으로 움직일 수 있는지를 구하는 문제이다. 따라서 정보들 중에서 내가 관심있게 보는 것은 ( ? , last )라는 정보가 중요하지만 동시에 ? 직전까지 움직일수 있느냐도 관건이다.
초기에 사람 수 만큼의 set을 준비해놓고 정보(a,b)가 들어오면 set[a]에 원소 b를 insert한다. 그리고 줄(order배열)의 맨 뒤에서 두 번째(주인공을 앞 사람)부터 last와 자리를 바꿀 수 있는지 확인한다. 확인하는 방법으로는 우선 set[a]에 last라는 원소가 있는지 확인해본다. 만약에 있다면 또 한가지 확인 과정을 거쳐야 하는데, 이전에 나왔던 사람들도 모두 원소로 갖고 있는지를 확인해보아야 한다. 예를 들어서 줄이 {3 1 2}형태로 서 있다고 해보자. 여기서 정보로 (3,2)가 들어왔다고 한들, 사이에 1이 가로막고있기 때문에 last인 2는 한 칸도 앞으로 움직일 수 없다. 따라서 3이 1과 교환할 수 있는 여지를 확인해본다는 의미이고 set[3]의 원소로 1이 있는지 확인해본다는 것이다. 따라서 정보로 교환될 수 없는 사람들을 별도로 저장하는 벡터인 v를 설정하고, 교환할 수 없을 때마다 v에 추가해야 한다.
주의할 점 :
-
배울 점 :
난이도 1800문제 중에서 수학적으로 연산을 취하는 것들은 나름 접근을 하겠는데, 이 문제처럼 수학보다는 아이디어적 접근을 하는 문제는 아직까지 약한 것 같다.
코드 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #include<stdio.h> #include<math.h> #include<string.h> #include<iostream> #include<functional> #include<string> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<assert.h> #include<stdlib.h> #include<stack> using namespace std; /*********************Contest Template***********************/ typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<long long,long long> pll; #define FASTIO ios_base::sync_with_stdio(false);cin.tie(0); struct S{ int a,b; S(){}S(int _a,int _b) { a=_a; b=_b; } const bool operator<(const S &o) const{ return a<o.a;} }; priority_queue<int,vector<int>,greater<int>> mpq; const int SPACE=0,NL=1; string exm; inline void showAll(vector<int> &v,int sep){ //0=space,1="\n" for(int &here:v) printf("%d%c",here,(sep)?'\n':' '); } inline void exf(void){ cout<<exm<<"\n"; exit(0); } inline vector<int> int_seperation(int N,int d=10){ vector<int> v; while(N){v.push_back(N%d); N/=d;} reverse(v.begin(),v.end()); return v; } /*********************Contest Template***********************/ const int SIZE= 300009; int order[SIZE]; set<int> si[SIZE]; int main(){ int n,m; scanf("%d %d",&n,&m); for(int i=1 ; i<=n ; i++){ scanf("%d",&order[i]); } while(m--){ int a,b; scanf("%d %d",&a,&b); si[a].insert(b); } vector<int> v; int last=order[n],ans=0; for(int i=n-1 ; i>=1 ; i--){ int cur=order[i]; bool possible=false; if(si[cur].count(last)){ possible=true; for(int here:v){ if(si[cur].count(here)==0){ possible=false; } } } if(possible) ans++; else v.push_back(cur); } printf("%d\n",ans); return 0; } /* */ | cs |
'Problem Solving > Greedy' 카테고리의 다른 글
[CF 1684C]Column Swapping (0) | 2022.06.15 |
---|---|
[CF 1667A] Make it Increasing (0) | 2022.06.15 |
[CF 898D] Alarm Clock (0) | 2019.06.28 |
[Codeforces 1153C] Serval and Parenthesis Sequence (0) | 2019.05.26 |
[Codeforces 950C] Zebras (0) | 2019.05.21 |