본문 바로가기

atcoder/abc

ABC308

나쁘지 않은 결과이다. 다시 민트에 올라왔으니 만족

 

0:00 ~ 1:30 - A 풀이

역시  구현이다. 오늘은 좀 귀찮은 구현이 나왔다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n, m;
string s,t,r;
set<ll> st;
int main(){
    fast;
    vector<ll> v(8);
    for(auto &i : v)cin>>i;
    auto e = v;
    sort(all(e));
    if(v!=e)return cout<<"No",0;
    for(int i = 0 ; i < 8 ; i++){
        if(100<=v[i] and v[i]<=675 and v[i]%25==0)continue;
        return cout<<"No",0;
    }cout<<"Yes";
}

 

1:30 ~ 4:57 - B 풀이

B는 또 뭐가 귀찮은게 많은 구현이다.

시간끌리기 좋은 문제이다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n, m;
string s,t,r;
set<ll> st;
ll no;
int main(){
    fast;
    cin>>n>>m;
    map<string, ll> M;
    vector<string> v(n);
    for(int i = 0 ; i < n ; i++)cin>>v[i];
    vector<string> e(m);
    for(int i = 0 ; i < m ; i++)cin>>e[i];
    cin>>no;
    for(int i = 0 ; i < m ; i++){
        ll a; cin>>a;
        M[e[i]]=a;
    }
    ll ans = 0;
    for(int i = 0 ; i < n ; i++){
        if(M.find(v[i])==M.end())ans += no;
        else ans += M[v[i]];
    }
    cout<<ans;
}

 

4:57 ~ 11:01 - C 풀이

C는 cmp 함수를 통해 그냥 정렬하는 문제

...

처럼 보이나 사실 실수오차를 없애는 방법을 찾는 문제이다.

정렬되었을 때 i<j이면

$$ \frac{A[i]}{A[i] + B[i]} > \frac{A[j]}{A[j] + B[j]}$$

를 만족해야 하므로 (인덱스는 알아서)

$$ A[i] * (A[i]+B[j]) > B[i] * (A[i] + B[i]) $$

를 만족하면 된다.

나눗셈이 곱셈이 되었으므로 실수오차를 없앨 수 있다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n;
typedef pair<pair<ll,ll>,ll> P;
vector<P> v;
bool cmp(P a, P b){
    if(a.first.first*b.first.second==b.first.first*a.first.second){
        return a.second < b.second;
    }
    return a.first.first*b.first.second > b.first.first*a.first.second;
}
int main(){
    fast;
    cin>>n;
    for(int i = 0 ; i < n ; i++){
        ll a,b; cin>>a>>b;
        v.push_back({{a,a+b},i+1});
    }
    sort(all(v), cmp);
    for(auto [a,b] : v)cout<<b<<" ";
}

 

11:01 ~ 16:51 - D 풀이

그냥 bfs 구현이다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n, m;
string s[505];
ll dx[] = {-1,1,0,0}, dy[] = {0,0,-1,1};
bool visited[505][505];
struct asdf{
    ll a,b;
    ll idx;
};
queue<asdf> q;
inline ll mod(ll x){ return x%5; }
string snuke = "snuke";
int main(){
    fast;
    cin>>n>>m;
    for(int i = 0 ; i < n ; i++)cin>>s[i];
    if(s[0][0] != snuke[0])return cout<<"No",0;
    q.push({0,0,1});
    visited[0][0]=1;
    while(q.size()){
        auto [x,y,idx] = q.front();
        q.pop();
        if(x==n-1 and y==m-1)break;
        for(int i = 0 ; i < 4 ; i++){
            ll nx = x+dx[i], ny = y+dy[i];
            if(nx<0 or ny<0 or nx>n-1 or ny>m-1)continue;
            if(visited[nx][ny])continue;
            if(snuke[idx] != s[nx][ny])continue;
            visited[nx][ny]=1;
            q.push({nx,ny,mod(idx+1)});
        }
    }
    cout<<(visited[n-1][m-1] ? "Yes" : "No");
}

 

16:51 ~ 31:25 - E 풀이

M,E,X 순서대로 배열되어야 하므로, E를 기준으로 M과 X를 세는 방법을 고려할 수 있다.

P_m[i][j]를 S[i] = 'M', A[i] = j인 prefix sum으로,

P_x[i][j]를 S[i] = 'X', A[i] = j인 suffix sum으로 정의하고,

E의 위치에 따라 m,x의 개수를 조합하여 해결하면 된다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n;
ll a[101010*2];
ll psum_m[202020][3];
ll psum_x[202020][3];
string s;
int main(){
    fast;
    memset(psum_m, -1, sizeof(psum_m));
    memset(psum_x, -1, sizeof(psum_x));
    cin>>n;
    for(int i = 0 ; i < 3 ; i++)psum_m[0][i] = psum_x[n+1][i] = 0;
    for(int i = 1 ; i <= n ; i++)cin>>a[i];
    cin>>s; s = '#' + s;
    for(int i = 1 ; i <= n ; i++){
        if(s[i]=='M'){
            psum_m[i][a[i]] = psum_m[i-1][a[i]]+1;
        }
        for(int j = 0 ; j < 3 ; j++){
            if(psum_m[i][j]==-1)psum_m[i][j] = psum_m[i-1][j];
        }
    }
    for(int i = n ; i >= 1 ; i--){
        if(s[i]=='X'){
            psum_x[i][a[i]] = psum_x[i+1][a[i]]+1;
        }
        for(int j = 0 ; j < 3 ; j++){
            if(psum_x[i][j]==-1)psum_x[i][j] = psum_x[i+1][j];
        }
    }
    ll ans = 0;
    for(int i = 2 ; i <= n ; i++){
        if(s[i]!='E')continue;
        for(int j = 0 ; j < 3 ; j++){
            for(int k = 0 ; k < 3 ; k++){
                ll mex = 0;
                if(a[i]==0 or j==0 or k==0){
                    mex++;
                    if(a[i]==1 or j==1 or k==1){
                        mex++;
                        if(a[i]==2 or j==2 or k==2){
                            mex++;
                        }
                    }
                }
                ans += (psum_m[i][j] * psum_x[i][k]) * mex;
            }
        }
    }
    cout<<ans;
}

 

31:25 ~ 43:54 - F 풀이

누가봐도 그리디다.

쿠폰을 매칭시키는 문제인데, 작은 가격의 값부터 보면서 현재 가격에서 가능한 쿠폰을 다 pq에 넣고 큰거부터 빼면 된다.

증명은 나중에 적겠다. 직관적으로 이 방법이 성립하는 이유는, 큰거에서 쓸 수 있는 쿠폰은 자명하게 작은거에서 쓸 수 있는 쿠폰을 모두 쓸 수 있으므로 작은것부터 고려해도 손해를 보지 않는다.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 998244353
typedef long long ll;
ll n, m;
ll p[202020];
pair<ll,ll> a[202020];
priority_queue<ll> pq;
int main(){
    fast;
    cin>>n>>m;
    for(int i = 1 ; i <= n ; i++)cin>>p[i];
    sort(p+1, p+n+1);
    for(int i = 1 ; i <= m ; i++)cin>>a[i].first;
    for(int i = 1 ; i <= m ; i++)cin>>a[i].second;
    sort(a+1, a+m+1);
    ll idx=1;
    for(int i = 1 ; i <= n ; i++){
        while(idx<=m and a[idx].first <= p[i]){
            pq.push(a[idx].second);
            idx++;
        }
        if(pq.empty())continue;
        p[i] -= pq.top();
        pq.pop();
    }
    ll ans = 0;
    for(int i = 1 ; i <= n ; i++)ans += p[i];
    cout<<ans;
}

43:54 ~ 100:00 - G 풀이 고민

f(x) := 현재 상태에서 xor을 x 이하로 할 수 있는가? 를 생각할 때,

M[i]를 i번 비트부터 29번 비트까지만 고려할때의 값이라 하면 M[i]에서 합이 2^(비트수)-2^i 꼴인 값이 존재할때 XOR값이 2^i 이하임을 이용해서 해결하려고 했으나, 구현이 복잡하여 하지 못했다.

공식 풀이는 인접한 원소에서만 최솟값이 나옴을 증명해서 구하는 것 같다.

 

다시 민트로 왔으니 블루까지 쭉 올라가야겠다.

 

'atcoder > abc' 카테고리의 다른 글

abc321  (2) 2023.09.23
abc320  (4) 2023.09.17
ABC319  (1) 2023.09.09
ABC318  (1) 2023.09.03
ABC306  (0) 2023.06.18