본문 바로가기

ps(알고리즘)

(32)
사탕상자 간단한 세그트리 응용 문제이다.세그트리에는 1부터 1000000까지의 맛이 각각 몇개 들어있는지 저장하면 된다.쿼리가 약간 다른데, 순위가 x인 사탕의 맛을 찾으려면 x가 seg[n*2]보다 크면 x에서 seg[n*2]를 빼고 seg[n*2+1]로 이동하면 되고,작으면 seg[n*2]로 이동하면 된다.#includeint N;long long M=1000000;long long seg[4000004];void update(long long n, long long s, long long e, long long ind, long long v){ if(ind어렵지 않으니 update와 find 함수 부분만 보면 바로 이해할 수 있다.
선분 그룹 이 문제는 왜 플레에 있는지 모르겠을 정도로 간단한데, 그냥 선분교차에 대한 처리 방법만 알면 된다.선분이 교차한다는 것은 한 선분을 기준으로, 나머지 선분의 두 점이 각각 다른 방향에 존재하는 것이다.여기서 방향은 전에 풀었던 convex-hull 에서 배웠던 ccw 함수를 쓰면 된다.그런데 방향이 달라도 직선이 아니라 선분이기 때문에 교차하지 않을 수 있다.따라서 한 선분만 기준으로 검사하는 것이 아니라, 각 선분을 기준으로 삼아서 검사를 두번 진행해야 한다.그리고 한가지 경우를 더 처리해야 하는데, 두 선분의 점 4개가 모두 일직선에 있을 경우이다.이 때는 한 선분의 max 꼭짓점이 다른 선분의 min꼭짓점보다 크기만 하면 교차한다. 이렇게 교차 여부 검사 함수만 짜면, 나머지는 그냥 이중for문을..
전깃줄-2 교차하지 않게 하기 위해서 없애야 하는 전깃줄을 구하는 것은 교차하지 않게 남길 수 있는 전깃줄의 최대 개수를 구하는것과 동일한다. 그리고 이것은 가장 긴 증가하는 부분수열과 같은 문제가 된다.없애야 하는 전깃줄 번호도 구해야 하기 때문에 이전에 풀었던 가장 긴 증가하는 부분수열 문제를 그냥 그대로 이용하면 된다.#include#include#includeusing namespace std;int N;vector>lines;vector lis;vector last;int ind[100004];void solve(){ for(auto i=lines.begin();i=0;i--) { if(ind[i]==ans) { //last.push_back(i); ..
볼록 껍질 convex hull 알고리즘을 구현하는 문제이다.알고리즘 자체는 엄청 간단한데, 일단 기준점을 하나 잡고 정렬을 해야 한다.아래에 있을수록, 왼쪽에 있을수록 작다는 기준으로 정렬을 해서 아래 왼쪽의 점 하나를 기준점으로 잡고,그 기준점을 기준으로 시계 방향에 있을수록 작다는 기준으로 또 한번 정렬을 한다.여기서 시계 방향에 있는지, 반시계 방향에 있는지를 구하는 알고리즘이 ccw이다.ccw는 벡터 외적으로 구하는데, 2차원 평면 상에서 벡터를 외적하면 k성분만 남는데, 이 방향이 시계 방향일 때는 +z방향,반시계 일때는 -z방향이라는 특징을 이용한다. 이제 점들을 돌면서 스택에 넣는다.  스택의 상위 2개 점 a,b를 뽑고, 봐야 할 점 c가 있을 때, bc가 ab보다 반시계 방향에 있으면 스택에 넣고..
Strongly Connected Componen scc 문제를 해결하는 알고리즘은 kosaraju와 tarjan 두가지가 있다.kosaraju 알고리즘은 두번의 dfs로 해결한다.먼저 첫번째 dfs 순회를 하면서 각 정점들에 대해 방문완료시간을 계산한다.방문완료시간을 기준으로 내림차순으로 역방향 그래프를 dfs로 순회한다.이때 나눠지는 그룹들이 scc가 된다.#include#include#includeusing namespace std;int V,E;vector adj[100004],radj[100004];int ft[100004];int visit[100004],rvisit[100004];int cnt;int sccnum;vector sccList[100004];int scc[100004];int used[100004];void dfs(int n){..
백조의 호수 문제를 보고 떠올린 해결책은 큐와 유니온파인드를 이용한 방식이다.일단 처음에 물을 큐에 담고 큐에서 하나씩 꺼내 보면서 상하좌우 네 방향에서 만약 물이면 유니온파인드로 합쳐주고,얼음이면 물로 바꾸고 큐에 날짜 정보를 포함시켜 담아준다.백조 두개의 유니온파인드 그룹이 같을 때까지 반복하면 되고, 모든 점은 한번씩만 큐에 저장되도록 하면최대 1500*1500만큼만 반복하면 되서 시간 안에 해결할 수 있다.근데 그렇게 코드를 짜고 예제까지 통과했는데 메모리 초과로 풀 수 없었다.맵에 대한 정보 1500*1500짜리 배열 말고도 유니온 파인드를 위한 1500*1500 배열이 하나 더 필요한데설마 1500*1500 배열 2개로 터질줄은 몰랐다. 어떻게 해야 할지 모르겠어서 그냥 찾아봤는데 놀랍게도 그냥 백조를 계..
책 페이지 그냥 0~9가 페이지에 몇번 등장하는지 카운팅하라는 단순한 문제이다.단순하게 생각해서 abcde 이렇게 다섯자리 수가 있다고 생각하자.이걸 다섯개 구간으로 나눠서 카운팅할건데 0~a0000, a0000~ab000, ab000~abc00, abc00~abcd0, abcd0~abcde이렇게 나눌 것이다. 이렇게 하는 이유는 자릿수가 하나 결정돼있으면 훨씬 세기 편해서이다.0~a0000을 보면, 1부터 9까지 보면서 숫자가 a보다 작으면 10의3승*a*4 + 10의4승 만큼 숫자가 나오고, a보다 크면 10의3승*a*4 이렇게 나온다. 그냥 카운팅이니 경우의 수 따지기를 잘 해보면 된다.이를 일반화 해보면 10^(digit-1)*a*digit+10^digit 이런식이다. 그리고 0은 1부터 N까지 숫자 구분없..
오아시스 재결합 스택을 이용해서 간단히 풀 수 있다.스택에 키를 넣으면서 만약 새로 들어온 키가 top보다 더 크면 어차피 top은 그 뒤의 사람을 볼 수 없기 때문에 제거하고, 새로 들어온 키가 더 작을 때까지 이를 반복하고 새로 들어온 키를 push해주면 된다. 한가지 고려해야 할 점은 키가 같은 경우이다. 키가 같으면 뒤의 사람까지 볼 수 있기 때문에 잘 처리해야 하는데, 이를 위해서 스택에 값을 넣을 때 pair로 넣어서 같은 키를 가진 사람이 몇명인지에 대한 정보를 추가로 전달해야 한다. 그래서 정리해보자면, 스택에 키를 넣으면서 top값과 비교하면 되는데1. 키가 top보다 큰 경우 - top은 더 이상 뒤에 있는 사람들을 못 보기 때문에 top의 키를 가진 사람만큼 쌍을 더하고, pop을 하고 계속 진행2...