https://codeforces.com/contest/1551/problem/C

 

Problem - C - Codeforces

 

codeforces.com

 

 

[난이도] Div.3
[유형] Greedy

[풀이]
n개의 a~e로 이루어진 문자열중에 i개의 문자열을 골랐을 때,
i개의 문자열에 포함된 한 문자(a~e 중 하나)가 나머지 문자들보다 많으면
이것을 Interesting story라고 합니다.

문제에서는 Interesting story를 만들 수 있으면서 i를 최대로 할때의 i값을 출력해야 합니다.

n제한 20만이기때문에 O(n)으로 해결해야 합니다.
Greedy 방식으로 해결이 가능합니다.

예를들어 n이 3이고 아래와 같이 문자열이 주어졌을 때,
bac
aaada
e

일단 알파벳이 a~e 5개밖에 안되기때문에
a가 제일 많은 경우, b가 제일 많은 경우 ... e가 제일 많은 경우
총 5가지의 경우를 가정하여 5가지를 모두 해보는 방식으로 접근합니다.

5가지 경우에 대해 문자열을 가장 많이 선택할 수 있는 경우의 문자열 갯수를 구하고
이중 최댓값이 정답이 됩니다.

bac [ a:1 , 나머지 :2]
aaada [ a:4 , 나머지 :1]
eaeeeb [ a:1 , 나머지 :5]
여기서 a가 가장 많은 경우를 구하면,
3개를 모두 선택하게 되면, a 6개, 나머지 8개로 Interesting story를 만족하지 못합니다.

그러므로 Interesting story가 될때까지 문자열을 한개씩 빼줘야 합니다.
여기서 Interesting story를 만들기 가장 유리한 순서로 문자열을 빼줍니다.
당연하게도 a의 개수보다 나머지 문자의 수가 많을수록 우선적으로 빼주는것이 유리합니다.
그말은 즉, Diff : (a의 개수) - (나머지 문자의 수) 가 작은 수부터 빼주는것이 유리하다는 말이됩니다.

위의 Diff를 각 문자열에 계산해보면
bac -> -1
aaada -> 3
eaeeeb -> -4
이므로 eaeeeb , bac 순으로 빼주는 것이 유리합니다.
vector에 Diff 값들을 넣어주고 정렬하면 순서대로 빼주는 것이 가능합니다.

3개의 문자를 포함했을때는 Diff가 -2였지만 eaeeeb를 빼줌으로써 +2가 됩니다.
전체 Diff가 양수가 되면 Interesting story를 만족하는 것이므로
a가 가장 많은 경우에 선택할 수 있는 문자열의 최대 수는 bac,aaada를 선택한 2가 됩니다.

b,c,d,e에 대해서도 위와 같은 연산을 해주고 이중 최댓값을 선택하면 됩니다.

 

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
int tc,n;
string arr[200001];

int getCnt(char target){
    int total_diff=0;

    vector<int> diff; // diff
    for(int i=0;i<n;i++){
        int cnt=0;
        for(char c : arr[i]){
            if(c==target){
                cnt++;
            }
        }
        int other = (int)arr[i].size()-cnt;
        diff.push_back(cnt-other);
        total_diff+=(cnt-other);
    }
    sort(diff.begin(),diff.end());
    for(int i=0;i<diff.size();i++){
        if(total_diff>0) {
            return n-i;
        }
        total_diff -= diff[i];
    }
    return 0;
}

void solve(){
    int ret=0;
    for(int i=0;i<5;i++){
        ret=max(ret,getCnt('a'+i));
    }
    cout <<ret<<'\n';
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> tc;
    while(tc--){
        cin >> n; 
        for(int i=0;i<n;i++) cin >> arr[i];
        solve();
    }
}

 

 

https://github.com/has2/Problem-Solving/blob/master/codeforces/Round734-Div.3/C.cpp

https://codeforces.com/contest/1551/problem/B1

 

Problem - B1 - Codeforces

 

codeforces.com

 

 

[난이도] Div.3
[유형] Greedy

[풀이]
어떤 알파벳이라 2개 이상이라면 레드,그린 각각 1개씩 밖에 들어갈수 없고,
1개만 있는 알파벳들은 어디든지 들어갈 수 있습니다.
이것을 이용하면
답은 (2개 이상인 알파벳의 개수)+(1개만 있는 알파벳의 개수)/2 인것을 알 수 있습니다.

 

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
int tc,n,a,b,cnt[26];
int main(){
    cin >> tc;
    while(tc--){
        string s;
        cin >> s;
        memset(cnt,0,sizeof(cnt));

        for(char c : s){
            cnt[c-'a']++;
        }

        int ans=0,remain=0;
        for(int i=0;i<26;i++){
            if(cnt[i]>=2) ans++;
            else if(cnt[i]==1) remain++;
        }
        printf("%d\n",ans+remain/2);
    }
}

 

https://github.com/has2/Problem-Solving/blob/master/codeforces/Round734-Div.3/B-1.cpp

https://codeforces.com/contest/1551/problem/A

 

Problem - A - Codeforces

 

codeforces.com

 

 

[난이도] Div.3
[유형] 수학

[풀이]
1) N%3==0
정확히 1:2로 나눠지므로
답은 c1: N/3 c2 : N/3

2) N%3==1
1 burle만 추가로 필요하므로
답은 c1: (N/3)+1 c2 : (N/3)

3) N%3==2
2 burle만 추가로 필요하므로
답은 c1: (N/3) c2 : (N/3)+1

 

#include <cstdio>
using namespace std;
int tc,n,a,b;
int main(){
    scanf("%d",&tc);
    while(tc--){
        scanf("%d",&n);
        int k = n/3;
        int mod = n%3;

        a=b=k;
        if(mod==1){
            a++;
        }else if(mod==2){
            b++;
        }
        printf("%d %d\n",a,b);
    }
}

 

https://github.com/has2/Problem-Solving/blob/master/codeforces/Round734-Div.3/A.cpp

https://www.acmicpc.net/problem/16928

 

16928번: 뱀과 사다리 게임

첫째 줄에 게임판에 있는 사다리의 수 N(1 ≤ N ≤ 15)과 뱀의 수 M(1 ≤ M ≤ 15)이 주어진다. 둘째 줄부터 N개의 줄에는 사다리의 정보를 의미하는 x, y (x < y)가 주어진다. x번 칸에 도착하면, y번 칸으

www.acmicpc.net

 

 

 

[난이도] Silver1
[유형] BFS

[풀이]
1. 사다리의 위치를 up[사다리의위치]=다음위치 , 뱀의 위치를 down[뱀의위치]=다음위치
와 같이 up,down 두개의 배열에 저장합니다.

2. 위치 1에서부터 BFS를 돌리며 현재 위치에서 k (1~6) 만큼 위로 올라가는 위치를 nxt로 둡니다.

3. up[nxt],down[nxt]가 0이 아니라면 nxt를 그 값으로 수정해줍니다.
문제 조건에 의해 사다리,뱀이 같이 있을 수 없으므로 up[nxt],down[nxt] 둘다 양수인 경우는 없습니다.

4. nxt를 방문하지 않았다면 q에 넣어줍니다. 모든 주사위 값(1~6)에 대해 루프를 돌면서 같은 연산을 해줍니다.

5. q의 front가 100이라면 답을 찾은 것이므로 현재까지 굴린 주사위 횟수를 출력하며 종료합니다.

 

#include <cstdio>
#include <queue>
using namespace std;
int N,M,u,v,up[101],down[101];
bool visit[101];
int main(){
    scanf("%d%d",&N,&M);
    while(N--) scanf("%d%d",&u,&v), up[u]=v;
    while(M--) scanf("%d%d",&u,&v), down[u]=v;

    queue<int> q;
    q.push(1);
    visit[1]=1;
    int ret=0;
    while(!q.empty()){
        int sz = q.size();
        while(sz--){
            int qf = q.front(); q.pop();
            if(qf==100){
                printf("%d",ret);
                return 0;
            }
            for(int k=1;k<7;k++){
                int nxt = qf+k;
                if(nxt>100) continue;
                int mv=0;
                if(up[nxt]) mv=up[nxt];
                if(down[nxt]) mv=down[nxt];
                if(mv!=0) nxt=mv;
                if(!visit[nxt]){
                    visit[nxt]=1;
                    q.push(nxt);
                }
            }
        }
        ret++;
    }
}

 

https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver1/16928.cpp

 

https://www.acmicpc.net/problem/1629

 

1629번: 곱셈

첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.

www.acmicpc.net

 

 

 

[난이도] Silver1
[유형] 분할정복

[풀이]
A를 B번 곱해야 하는데 B의 범위가 int의 최댓값 까지이므로 직접 곱해서는
시간내에 해결이 불가능합니다.
그러므로 A^2n = A^n*A^n인 거듭제곱의 성질을 이용한 분할정복으로 문제를 해결할 수 있습니다.

각 재귀 호출 sol(n)에서 sol(n/2)을 호출하여 이 값을 제곱해주고
만약 n이 홀수인경우 이 값에 A를 추가로 한번 더 곱해준 값을
리턴해주면 O(lgN)의 시간복잡도로 답을 구할 수 있습니다.

A의 최댓값 역시 int의 최댓값 까지이므로 연산시 오버플로우 방지를 위해 long long 자료형을 이용하였습니다.

 

 

#include <cstdio>
using ll = long long;
ll A,B,C;
ll sol(ll n){
    if(n==1) return A; 
    ll ret = sol(n/2);
    ret = (ret*ret)%C;
    if(n%2) ret=(ret*A)%C;
    return ret;
}
int main(){
    scanf("%lld%lld%lld",&A,&B,&C);
    printf("%lld",sol(B)%C);
}

 

https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver1/1629.cpp

https://www.acmicpc.net/problem/11659

 

11659번: 구간 합 구하기 4

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j

www.acmicpc.net

 

 

 

[난이도] Silver3
[유형] 누적합

[풀이]
구간합 배열 sum을 만들어놓고 sum[j]-sum[i] 형태로 모든 쿼리에 O(1)로 출력이 가능합니다.

 

 

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
fun main() = with(BufferedReader(InputStreamReader(System.`in`))){
    var (N,M) = readLine().split(' ').map{it.toInt()}
    val arr = readLine().split(' ').map{it.toInt()}
    val sum = Array<Int>(N){0}
    sum[0]=arr[0]
    for(i in 1 until N) sum[i] = sum[i-1]+arr[i]
    while(M-->0){
        val ip = readLine().split(' ')
        val i = ip[0].toInt()
        val j = ip[1].toInt()
        println(sum[j-1]-(if(i==1) 0 else sum[i-2]))
    }
}

 

https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver3/11659.cpp

https://www.acmicpc.net/problem/11286

 

11286번: 절댓값 힙

첫째 줄에 연산의 개수 N(1≤N≤100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 0이 아니라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0

www.acmicpc.net

 

 

 

[난이도] Silver1
[유형] 우선순위큐

[풀이]
maxHeap, minHeap 두가지를 이용하면 답을 구할 수 있습니다.
pair(abs(x),x) 를 저장하는 Heap 한개로도 문제를 풀수 있습니다.

 

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
import kotlin.math.abs
const val mxN = 1 shl 31
fun main() = with(BufferedReader(InputStreamReader(System.`in`))){
    val minHeap = PriorityQueue<Int>()
    val maxHeap = PriorityQueue<Int>{a,b->b.compareTo(a)}
    repeat(readLine().toInt()){
        val v = readLine().toInt()
        when{
            v==0->{
                var ret=0
                if(!minHeap.isEmpty() || !maxHeap.isEmpty()){
                    ret = when {
                        minHeap.isEmpty() -> maxHeap.poll()
                        maxHeap.isEmpty() -> minHeap.poll()
                        else -> if(abs(minHeap.peek()) < abs(maxHeap.peek())) minHeap.poll() else maxHeap.poll()
                    }
                }
                println(ret)
            }
            v<0 -> maxHeap.add(v)
            else -> minHeap.add(v)
        }
    }
}

 

https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver1/11286.cpp

https://www.acmicpc.net/problem/9375

 

9375번: 패션왕 신해빈

첫 번째 테스트 케이스는 headgear에 해당하는 의상이 hat, turban이며 eyewear에 해당하는 의상이 sunglasses이므로   (hat), (turban), (sunglasses), (hat,sunglasses), (turban,sunglasses)로 총 5가지 이다.

www.acmicpc.net

 

 

[난이도] Silver3
[유형] Map

[풀이]

각 옷의 종류를 map<String,Int> 의 키로 하여 각 옷의 종류마다 몇개의 옷이 있는지 value로 저장합니다. 

그 뒤 모든 (value+1)을 곱해준 값에서 1을 빼준 값이 정답이 됩니다.

value에 1을 더해주는 이유는 이 종류의 옷을 입지 않은 경우의 수이며

마지막에 1을 빼주는 이유는 아무 종류의 옵도 입지 않은 경우는 제외시켜야 하기 때문입니다.

 

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
fun main() = with(BufferedReader(InputStreamReader(System.`in`))){
    var tc = readLine().toInt()
    while(tc-->0) {
        var N = readLine().toInt()
        val mp = HashMap<String, Int>()
        for(i in 0 until N) {
            val a = readLine().split(" ")[1]
            if(mp.containsKey(a)) mp[a] = 1+mp[a]!!
            else mp[a] = 1
        }
        var ans=1
        for(a in mp.values) ans*=(a+1)
        println(ans-1)
    }
}

https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver3/9375.cpp

+ Recent posts