sort(arr, arr + n); int a, b; a = b = -1; for(i = n - 2; i >= 0; i--) if(!chk[i + 1] && arr[i] == arr[i + 1]) if(a == -1) a = arr[i]; else b = arr[i];

Similar documents
untitled

C프로-3장c03逞풚

Run 봄 연습 Mar 18 Mar 24, 2018, Week 3 문제 1. 초코바 입력 파일: 출력 파일: 시간 제한: 메모리 제한: standard input standard output 1 seconds 128 megabytes H W 격자 모양의 초콜릿이 있다.

2002년 2학기 자료구조

untitled

중간고사

; struct point p[10] = {{1, 2, {5, -3, {-3, 5, {-6, -2, {2, 2, {-3, -3, {-9, 2, {7, 8, {-6, 4, {8, -5; for (i = 0; i < 10; i++){ if (p[i].x > 0 && p[i

Chap 6: Graphs

untitled

ePapyrus PDF Document

chap 5: Trees

특허청구의 범위 청구항 1 앵커(20)를 이용한 옹벽 시공에 사용되는 옹벽패널에 있어서, 단위패널형태의 판 형태로 구성되며, 내부 중앙부가 후방 하부를 향해 기울어지도록 돌출 형성되어, 전면이 오 목하게 들어가고 후면이 돌출된 결속부(11)를 형성하되, 이 결속부(11

: 1 int arr[9]; int n, i; printf(" : "); scanf("%d", &n); : : for(i=1; i<10; i++) arr[i-1] = n * i; for(i=0; i<9; i++) if(i%2 == 1) print

와플-4년-2호-본문-15.ps

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

K&R2 Reference Manual 번역본

(지도6)_(7단원 202~221)

(Microsoft Word - \301\337\260\243\260\355\273\347.docx)

금오공대 컴퓨터공학전공 강의자료

chap01_time_complexity.key

Microsoft PowerPoint - chap11-포인터의활용.pptx

Microsoft PowerPoint - chap05-제어문.pptx

Microsoft PowerPoint - chap03-변수와데이터형.pptx

Microsoft PowerPoint - chap10-함수의활용.pptx

C++ Programming

프로그래밍개론및실습 2015 년 2 학기프로그래밍개론및실습과목으로본내용은강의교재인생능출판사, 두근두근 C 언어수업, 천인국지음을발췌수정하였음

Infinity(∞) Strategy

Microsoft PowerPoint - chap04-연산자.pptx


6장정렬알고리즘.key

Microsoft PowerPoint - chap12-고급기능.pptx

02장.배열과 클래스

OCW_C언어 기초

Line (A) å j a k= i k #define max(a, b) (((a) >= (b))? (a) : (b)) long MaxSubseqSum0(int A[], unsigned Left, unsigned Right) { int Center, i; long Max

, ( ),, ( ), 3, int kor[5]; int eng[5]; int Microsoft Windows 4 (ANSI C2 ) int kor[5] 20 # define #define SIZE 20 int a[10]; char c[10]; float

Data structure: Assignment 3 Seung-Hoon Na December 14, 2018 레드 블랙 트리 (Red-Black Tree) 1 본 절에서는 레드 블랙 트리를 2-3트리 또는 2-3-4트리 대한 동등한 자료구조로 보고, 두 가지 유형의 레

금안13(10)01-도비라및목차1~13

<C1DFB0EDB5EEBACE2E687770>

문제는다양한방법으로풀수있으며, 다음의풀이는여러해법중하나이다. [ 문제 1] 밀도구하기 질량밀도 이다. 물체의질량 M과부피 V가주어지면밀도는 M/V로구할수있다. 부피 여기서질량 M 과부피 V 는정수이지만 M/V 은실수가될수있기때문에 M 과 V 를받 을때실수로입력받는다.

Microsoft PowerPoint - [2009] 02.pptx

PowerPoint 프레젠테이션

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

04 Çмú_±â¼ú±â»ç

C 언어 프로그래밊 과제 풀이

chap7.key

슬라이드 1

<BAB0C3B7322E20B7CEB5E5B8CABCBCBACEB0FAC1A62E687770>

Microsoft PowerPoint - ch07 - 포인터 pm0415

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

03장.스택.key

Chapter 4. LISTS

Let G = (V, E) be a connected, undirected graph with a real-valued weight function w defined on E. Let A be a set of E, possibly empty, that is includ

<4D F736F F D B5B6C0DABDC5BFEBB5EEB1DE20B5B5C0D4B0FA20B1E2BEF720BDC5BFEBC0A7C7E820BBF3BDC320C6F2B0A120B5EEC0C720BFB5C7E2C0BA2E646F63>

<4D F736F F F696E74202D20C1A63132B0AD20B5BFC0FB20B8DEB8F0B8AEC7D2B4E7>

int main(void) int a; int b; a=3; b=a+5; printf("a : %d \n", a); printf("b : %d \n", b); a b 3 a a+5 b &a(12ff60) &b(12ff54) 3 a 8 b printf(" a : %x \

PowerPoint 프레젠테이션

Microsoft PowerPoint - Java7.pptx

제 11 장포인터 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

Microsoft PowerPoint - chap-11.pptx

11강-힙정렬.ppt

WISHBONE System-on-Chip Interconnection Architecture for Portable IP Cores


The C++ Programming Language 5 장포인터, 배열, 구조체 5.9 연습문제 다음의선언문을순서대로작성해보자. 문자에대한포인터, 10개정수의배열, 10개정수의배열의참조자, 문자열의배열에대한포인터, 문자에대한포인터에대한포인터, 상수정수, 상수

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

쉽게 배우는 알고리즘 강의노트

풀이이문제는점의집합을확장하는규칙과시작점이주어졌을때, 목표로하는점을만들수있는지의여부를판단하는문제이다. 가능한모든점을직접만들어보는식으로는해결할수없으므로, 점을생성하는규칙에대해서수학적으로분석하는방식으로처리해야한다. 먼저시작점이 (a, a+x) 라고하면, 규칙 1을반복적용해서

본 발명은 중공코어 프리캐스트 슬래브 및 그 시공방법에 관한 것으로, 자세하게는 중공코어로 형성된 프리캐스트 슬래브 에 온돌을 일체로 구성한 슬래브 구조 및 그 시공방법에 관한 것이다. 이를 위한 온돌 일체형 중공코어 프리캐스트 슬래브는, 공장에서 제작되는 중공코어 프

PowerPoint 프레젠테이션

1. 표준입출력 C++ : C의모든라이브러리를포함 printf, scanf 함수사용가능예 : int, double, 문자열값을입력받고출력하기 #include <cstdio> int ivar; double dvar; char str[20]; printf("int, dou

PowerPoint 프레젠테이션

untitled

Chapter_06

4. 1 포인터와 1 차원배열 4. 2 포인터와 2 차원배열 4. 3 포인터배열 4. 4 포인터와문자그리고포인터와문자열

Microsoft PowerPoint - slide06.pptx

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

Data structure: Assignment 1 Seung-Hoon Na October 1, Assignment 1 Binary search 주어진 정렬된 입력 파일이 있다고 가정하자. 단, 파일내의 숫자는 공백으로 구 분, file내에 숫자들은

adfasdfasfdasfasfadf

<C1DF29BCF6C7D020315FB1B3BBE7BFEB20C1F6B5B5BCAD2E706466>

쉽게배우는알고리즘 9장. 그래프알고리즘



슬라이드 1


歯9장.PDF

Java

2015 개정교육과정에따른정보과평가기준개발연구 연구책임자 공동연구자 연구협력관

Microsoft PowerPoint - Chapter 10.ppt

11장 포인터

C++ Programming

0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4

»ê¾÷¿¬±¸¿øÇ¥Áö

본 강의에 들어가기 전

2/26(목) 두산 A+/부정적 A/안정적 - 두산그룹 사업지주회사로서 주력 자회사인 두산중공업 신용등급 변경 감안해 신용등급 하향 2/26(목) SK 에너지 AA+/부정적 AA/안정적 년까지 중국 및 아시아 신흥국 중심으로 증설이 예정되어 있어 석유제품

설계란 무엇인가?

chap8.PDF

Microsoft PowerPoint - C++ 5 .pptx

Transcription:

Run@KAIST 2주차 연습 20160021 Hanpil Kang Mar 11 Mar 17, 2018 1 A to Z 쉬운 문제입니다. 가장 왼쪽에 있는 A와 가장 오른쪽에 있는 Z를 잡아서 부분문자열을 만들면 됩니다. #include<bits/stdc++.h> int N; char s[202020]; cin >> s; N = strlen(s); int a,z; for(int i=0; i<n;++i) if(s[i]== A ) a=i; break; for(int i=0; i<n; ++i) if(s[i]== Z ) z=i; cout << z-a+1 << endl; 2 직사각형 직사각형을 만들려면, 길이가 같은 막대를 모은 한 쌍이 두 개 필요합니다. 그런 쌍 들이 여러개 있다면, 그 중 가장 큰 2개를 고르는게 답이 됩니다. #include<bits/stdc++.h> int arr[100010]; bool chk[100010]; int n, i; scanf("%d", &n); for(i = 0; i < n; i++) scanf("%d", &arr[i]); 1

sort(arr, arr + n); int a, b; a = b = -1; for(i = n - 2; i >= 0; i--) if(!chk[i + 1] && arr[i] == arr[i + 1]) if(a == -1) a = arr[i]; else b = arr[i]; break; chk[i] = 1; if(b == -1) printf("0"); else printf("%lld", 1LL * a * b); 3 음식 맛있게 먹기 Dn 을, An 에서 끝나게 연속한 음식을 먹는 방법중 맛있음이 가장 최대의 것이라고 합시다. 그러면 Dn 은, n 1번째 음식을 먹거나, 안먹는 두가지의 경우가 있습니다. n 1번째 음식을 먹을 경우에는, n번째 음식을 포함해서 n 1번째 에서 최대의 맛있음을 가지는 음식까지를 먹으면 됩니다. n번째 음식을 먹는 경우는 한 가지밖에 없습니다. 그래서 이 두개의 최댓값을 구해주시면 Dn 이 나오게 되고, D1 부터 DN 까지 차례로 구한 후 최댓값이 답이 되게 됩니다. 아래의 코드의 d가 Dn 의 역할을 하게 됩니다. #include <cstdio> long long maxsum(int N, int A[]) long long ans = A[0], d = 0; for(int i=0; i<n; ++i) d += A[i]; if(ans<d) ans = d; if(d<0) d = 0; return ans; int N; scanf("%d", &N); int *A = new int[n]; for(int i=0; i<n; ++i) scanf("%d", A+i); printf("%lld\n", maxsum(n, A)); 2

4 조상 트리를 구간으로 바꾸는 테크닉을 알면 쉽습니다. 트리의 루트로 부터 시작해서, dfs를 돌면서 dfs-order를 기억해 줍시다. 어떤 노드에서 dfs를 시작해서, dfs를 나갈 때 dfs-order를 A, B라 하면, 그 노드의 subtree 에 있는 수는 [A, B] 구간이 되게 됩니다. 이것을 이용해서, 하나가 다른 하나의 포함되는지로 조상인지 아닌지의 여부를 판단할 수 있습니다. #include <vector> #include <cstdio> const int MAX_N = 1e5 + 10; vector<int> Ed[MAX_N]; int L[MAX_N], R[MAX_N], TN; void dfs(int v, int p) L[v] = ++TN; for(int w : Ed[v]) if(w!= p) dfs(w, v); R[v] = TN; void init(int N, int R, int P[]) for(int i=0; i<n; i++) if(i+1!= R) Ed[i+1].push_back(P[i]); Ed[P[i]].push_back(i+1); dfs(r, 0); bool isancestor(int A, int B) return L[A] <= L[B] && R[B] <= R[A]; int N, R, Q; scanf("%d%d%d", &N, &R, &Q); int *P = new int[n]; for(int i=0; i<n; ++i) scanf("%d", P+i); init(n, R, P); for(int i=0; i<q; ++i) int A, B; scanf("%d%d", &A, &B); if(isancestor(a, B)) puts("yes"); else puts("no"); 3

5 혜아 인 어비스 이 문제는 running median이라고도 알려진 유명한 문제입니다. 이 문제를 풀 때 Balanced Binary Search Tree등을 이용하는 법도 있지만, Heap (Priority Queue)를 이용한 풀이가 간단하기 때문에 설명하겠습니다. 숫자들이 N 개가 있으면, 큰 숫자로 부터 세어 (N + 1)/2개를 min-heap에, 하위 (N 1)/2개를 max-heap에 담아 줍시다. 그러면 중간값은 min-heap의 최솟값이라는 것을 알 수 있습니다. 숫자 2개가 들어오면, 숫자가 중간값보다 큰지 작은지에 따라 힙에 넣어줍니다. 그리고 숫자 갯수가 맞지 않으면, max-heap 또는 min-heap 중에 크기가 큰 쪽에서 최댓값 또는 최솟값을 빼서 반대쪽에 넣어줍니다. 이 과정을 통하면, min-heap과 max-heap의 크기를 (N + 1)/2와 (N 1)/2로 계속 유지하는 것이 가능합니다. 시간복잡도는 쿼리당 O(log N )이고 상수가 크지도 않습니다. #include<queue> #include<vector> #include<functional> #include<cstdio> priority_queue<int> lessq; priority_queue<int, vector<int>, greater<int> > greaterq; void init(int X) lessq.push(x); int recruit(int X, int Y) if(x > lessq.top()) greaterq.push(x); else lessq.push(x); if(y > lessq.top()) greaterq.push(y); else lessq.push(y); if(lessq.size() == greaterq.size() + 3) greaterq.push(lessq.top()); lessq.pop(); if(lessq.size() + 1 == greaterq.size()) lessq.push(greaterq.top()); greaterq.pop(); return lessq.top(); int X; scanf("%d", &X); init(x); int T; scanf("%d", &T); for(int i=0; i<t; ++i) int A, B; scanf("%d%d", &A, &B); printf("%d\n", recruit(a, B)); 4

6 도시 연결 이 문제는 Minimum Spanning Tree로 잘 알려진 문제입니다. Minimum Spanning Tree란, 그래프의 부분 그래프 중에서 최소 가중치의 연결 그래프를 의미합니다. Kruskal, Prim, Boru vka등의 알고리즘이 있지만, 여기서는 제일 구현하기 간편한 Kruskal Algorithm을 설명합시다. Kruskal 알고리즘은, 간선을 가중치 순서대로 정렬합니다. 그 다음에 작은 것 부터 시작해서, 사이클이 없을 경우에 그 간선을 선택해 줍니다. 그래서 N 1개의 간선이 선택되어 스패닝 트리를 만들 때 까지 반복 해 줍니다. 이러면 답을 얻을 수 있습니다. 이 알고리즘이 올바르다는 것을 증명하기 위해서는 두 가지를 보여야 합니다. 1. 이 알고리즘은 언제나 Spanning Tree를 만든다.: 일단 이 그래프에서는 사이클이 생길 수 없습니다. 항상 다른 두 트리간에 연결을 한다는 점에서 알 수 있습니다. 그리고 그래프는 연결그래프 입니다. 왜냐하면 그래프가 두 부분 이상으로 나눠져 있다면, 알고리즘은 그 엣지를 처음 봤을 때 이어야 합니다. 2. 이 알고리즘은 최소 Spanning Tree를 찾는다.: 스패닝 트리를 만드는 과정 중에 항상 그 스패닝 트리를 포함하는 최소 스패닝 트리가 있음을 보이면 됩니다. 수학적 귀납법을 사용하여, T 에서 e 라는 엣지를 추가하려고 합니다. T 를 포함하는 최소 스패닝 트리인 M 이 존재하고, M + e에는 사이클이 존재합니다. 이 사이클에서 T 에 포함되지 않는 최소 원소인 f 가 존재 합니다. M 이 최소 스패닝 트리라서, f 의 가중치는 e의 가중치 보다 크지 못하기 때문에, M + e f 도 또 다른 최소 스패닝 트리이고, 수학적 귀납법에 의해서 계속 최소 스패닝 트리가 만들어 진다는 것을 알 수 있습니다. 증명과정이 어렵지만, Minimum Spanning Tree의 성질이 굉장히 좋다고 생각하시면 될 것 같습니다. #include <vector> #include <algorithm> #include <cstdio> struct ED int a, b, c; ED(int aa, int bb, int cc) : a(aa), b(bb), c(cc) bool operator<(const ED &o) return c < o.c; ; struct UF vector<int> UNF; UF(int N) : UNF(vector<int>(N+10, 0)) for(int i=0; i<n+10; i++) UNF[i] = i; int Find(int v) return UNF[v] == v? v : UNF[v] = Find(UNF[v]); bool Union(int a, int b) UNF[a = Find(a)] = (b = Find(b)); return a!= b; ; vector<ed> Ed; int mincost(int N, int M, int A[], int B[], int C[]) for(int i=0; i<m; i++) Ed.emplace_back(A[i], B[i], C[i]); sort(ed.begin(), Ed.end()); UF uf = UF(N); int ans = 0, cnt = 0; for(ed &e : Ed) if(uf.union(e.a, e.b)) ans += e.c, cnt++; 5

return (cnt == N-1? ans : -1); int N, M; scanf("%d%d", &N, &M); int *A = new int[m], *B = new int[m], *C = new int[m]; for(int i=0; i<m; ++i) scanf("%d%d%d", A+i, B+i, C+i); printf("%d\n", mincost(n, M, A, B, C)); 7 헤아의 타이핑 혜아의 타이핑 문제에서 답은 s의 길이가 같으면, 어떤 것이든 상관이 없다는 것을 알 수 있습니다. 그래서 우리는 s의 길이가 되게 타이핑 하는 방법의 수를 센 후에, 2 s 로 답을 나눠 줄 것입니다. ( mod M 에서 M +1 2로 나누는 법은 를 곱하시면 됩니다.) 2 그래서 이 문제는 동적계획법 테이블 Di,j 를, 키를 i번 쳤을 때, j개의 글자가 써져 있는 경우의 수를 O(N 2 )에 구하고, DN, s 의 값을 2 s 로 나눈 값을 출력해 주면 됩니다. #include<bits/stdc++.h> long long dp[5050][5050]; //i keystroke, j remain int N; const int MOD = 1e9+7; const int MODINV = (MOD+1)/2; char s[10101]; scanf("%d%s", &N, s); int K = strlen(s); dp[0][0] = 1; for(int i=0; i<=n; ++i) for(int j=0; j<=i; ++j) dp[i][j] %= MOD; dp[i+1][max(j-1, 0)] += dp[i][j]; dp[i+1][j+1] += 2*dp[i][j]; long long ans = dp[n][k]; for(int i=0; i<k; ++i) ans = (ans*modinv)%mod; printf("%lld\n", ans); 8 돌 돌 문제의 제한은 Backtracking이나 Branch and Bound같은 알고리즘을 떠올리게 합니다. 하지만 이 문제에는 다항시간 풀이법이 존재합니다. 6

우리는 이 문제를 다음과 같은 방법으로 min-cut으로 바꿀 것 입니다.: S를 부숴진 돌의 집합, T 를 부숴지지 않은 돌의 집합이라고 합시다. 우리는 모든 음수인 돌을 전부 부수는게 (가능하다면) 최적이라는 것을 알고 있습니다. 그래서 S에 부수려는 돌을, T 에 부수지 않았으면 하는 돌을 배치 합니다. 그리고 i가 S에 속하면, i의 배수는 T 에 속하지 못한다는 것을 알 수 있습니다. (이렇지 않은 경우에는 전부 가능합니다.) 그래서 우리는 다음과 같이 모델링을 할 수 있습니다. j가 i의 배수인데, j가 T 에, i가 S에 들어가 있으면, ai 0이고, i가 T 에 들어가 있으면, ai, ai > 0이고, i가 S에 들어가 있으면, ai 의 패널티를 받는다고 생각할 수 있습니다. 그래서 이 패널티를 기준으로 다음과 같은 그래프를 만듭니다. ai 0 이면 S i로 가중치 ai 의 간선 ai > 0 이면 i T 로 가중치 ai 의 간선 j = ni (n > 2)에 대해, i j로 가중치 의 간선 Flow-cut duality에 의해, S에서 T 까지 flow를 흘려주면 최소 패널티를 구할 수 있고, 정점 O(N ), 간선 O(N logn )개가 나오기 때문에, 흔한 플로우 알고리즘인 BFS Ford-Fulkerson Algorithm 같은 알고리즘으로도 O(N 3 log 2 N )으로 시간 안에 돌게 됩니다. #include<bits/stdc++.h> const int MAXN = 505; struct edgint pos; long long cap; int rev;; vector<edg> gph[maxn]; void clear()for(int i=0; i<maxn; i++) gph[i].clear(); void add_edge(int s, int e, long long x) gph[s].push_back(e, x, (int)gph[e].size()); gph[e].push_back(s, 0, (int)gph[s].size()-1); int dis[maxn], pnt[maxn]; bool bfs(int src, int sink) memset(dis, 0, sizeof(dis)); memset(pnt, 0, sizeof(pnt)); queue<int> que; que.push(src); dis[src] = 1; while(!que.empty()) int x = que.front(); que.pop(); for(auto &e : gph[x]) if(e.cap > 0 &&!dis[e.pos]) dis[e.pos] = dis[x] + 1; que.push(e.pos); return dis[sink] > 0; long long dfs(int x, int sink, long long f) 7

if(x == sink) return f; for(; pnt[x] < gph[x].size(); pnt[x]++) edg e = gph[x][pnt[x]]; if(e.cap > 0 && dis[e.pos] == dis[x] + 1) long long w = dfs(e.pos, sink, min(f, e.cap)); if(w) gph[x][pnt[x]].cap -= w; gph[e.pos][e.rev].cap += w; return w; long long match(int src, int sink) long long ret = 0; while(bfs(src, sink)) long long r; while((r = dfs(src, sink, (long long)2e9))) ret += r; return ret; int a[maxn]; int N; scanf("%d", &N); long long ans = 0; for(int i=1; i<=n; ++i) scanf("%d", a+i); if(a[i]>0) ans += a[i]; int S = N+1; int T = N+2; for(int i=1; i<=n; ++i) if(a[i] <= 0) add_edge(s, i, -a[i]); else add_edge(i, T, a[i]); for(int i=1; i<=n; ++i) for(int j=2*i; j<=n; j += i) add_edge(i, j, (long long)(1e18)); printf("%lld\n", ans - match(s, T)); 8