Codeforces Round 702 (Div.3)
Updated:
A. Dense Array
$a_i$와 $a_{i+1}$이 $2a_i ≤ a_{i+1}$ (or $2a_{i+1} ≤ a_i$)의 식을 만족하지 않으면 두 수 사이에 조건을 만족하는 숫자를 집어넣는 문제
$a_i$에서 시작하여 2씩 곱해가면서 $a_{i+1}$보다 같거나 작을 때까지 반복하면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
#define ll long long
using namespace std;
void solve() {
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
int ans=0;
for(int i=0;i<n-1;i++) {
int m=min(a[i],a[i+1]), M=max(a[i],a[i+1]);
while(m*2<M) {
ans++;
m*=2;
}
}
cout<<ans<<endl;
return;
}
int main() {
int t;
cin>>t;
while(t--) {
solve();
}
return 0;
}
B. Balanced Remainders
$a$배열에서 3으로 나눈 나머지인 0, 1, 2의 숫자가 같을 때까지 $a$배열의 원소를 +1 연산의 최소 수를 구하는 문제
$c_i$가 모두 같게 하기 위해서는 $c_i=\frac{n}{3}$을 만족해야 한다. 그래서 $c_i>\frac{n}{3}$인 $i$를 가장 먼저 찾는다.
$a$배열에서 $i$번째 원소를 +1 증가하는 것은 $c_i$의 개수는 -1, $c_{i+1}$의 개수는 +1인 것을 의미한다.
그래서 위의 과정을 반복하여 횟수를 세어준다.
#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
#define ll long long
using namespace std;
void solve() {
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
int res=0;
vector<int> cnt(3);
for(int i=0;i<n;i++) {
for(int j=0;j<=2;j++) {
if(a[i]%3==j) cnt[j]++;
}
}
while(*min_element(cnt.begin(),cnt.end())!=n/3) {
for(int i=0;i<3;i++) {
if(cnt[i]>n/3) {
res++
cnt[i]--;
cnt[(i+1)%3]++;
}
}
}
cout<<res<<endl;
return;
}
int main() {
int t;
cin>>t;
while(t--) {
solve();
}
return 0;
}
C. Sum of Cubes
어떠한 수 $x$에 대해 $a^3+b^3=x$를 만족하는 $a$,$b$가 존재하는 지 찾는 문제
$a$,$b$가 양수이기 때문에 $a^3$, $b^3$또한 양수이다. 그러므로 $a^3 ≤ a^3+b^3 ≤ x$ 를 만족하기 때문에 $a$는 1부터 $\sqrt[3]{x}$까지만 탐색하면 된다.
따라서 $a$의 범위는 $1 ≤ a ≤ 10^4$이다.
각 $a$에 따라 $b$는 $b=\sqrt[3]{x-a^3}$을 만족하는데 $b$가 정수인지 확인하면 된다.
#include <iostream>
#include <unordered_set>
#define endl '\n';
#define ll long long
using namespace std;
const ll N = 1000000000000L;
unordered_set<ll> cubes;
void precalc() {
for(ll i=1;i*i*i<=N;i++) {
cubes.insert(i*i*i);
}
}
void solve() {
ll x;
cin>>x;
for(ll i=1;i*i*i<=x;i++) {
if(cubes.count(x-i*i*i)) {
cout<<"YES"<<endl;
return;
}
}
cout<<"NO"<<endl;
return;
}
int main() {
precalc();
int t;
cin>>t;
while(t--) {
solve();
}
return 0;
}
D. Permutation Transformation
재귀적으로 트리를 만들어야 한다. 먼저, $(l,r,d)$ 인자를 정의한다.
- $[l,r]$구간에서의 깊이 $d$
이제 다음의 과정을 따라가면서 해결한다.
- 구간 $[l,r]$에서의 최대 값 $a_m$의 위치 $m$를 찾는다. $(a_m=max^{r}_{i=l}a_i)$
- 정점 $a_m$의 깊이는 $d$이다.
- 만약, $l<m$이라면, 다음 상태 $(l,m-1,d+1)$로 들어간다.
- 만약, $m<r$이라면, 다음 상태 $(m+1,r,d+1)$로 들어간다.
#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
using namespace std;
void build(int l, int r, vector<int> const &a, vector<int> &d, int curD=0) {
if(r<l) return;
if(l==r) {
d[l]=curD;
return;
}
int m=l;
for(int i=l+1;i<r;i++) [
if(a[m]<a[l]) m=i;
}
d[m]=curD;
build(l,m-1,a,d,curD+1);
build(m+1,r,a,d,curD+1);
}
void solve() {
int n;
cin>>n;
vector<int> a(n);
for(int &x : a) cin>>x;
vector<int> d(n);
build(0,n-1,a,d);
for(int x : d) cout<<x<<' ';
cout<<endl;
return;
}
int main() {
int t;
cin>>t;
while(t--) {
solve();
}
return 0;
}
E. Accidental Victory
$i$번째 플레이어가 $a_i$개의 토큰을 가지고 있을 때 문제의 조건에 따라서 $i$번째 플레이어가 이길 수 있는지 확인하는 문제이다.
$a$가 [1,2,3,4]일때, 토큰 3개를 가지고 있는 플레이어가 이길 수 있다면, 3개보다 많은 토큰을 가진 플레이어들은 모두 이길 수 있다.
반면에, 토큰 3개를 가진 플레이어가 이길 수 없다면, 3개보다 적은 토큰을 가진 플레이어들은 모두 이길 수 없다.
따라서, 이분탐색으로 어떤 플레이어가 이길 수 있는지 없는지 확인하는 과정이 필요하다.
확인하는 과정은 어떤 토큰 $x$가 $x$보다 작은 토큰을 모두 가져가서 오른쪽 플레이어들을 이길 수 있는지 체크하면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;
void solve() {
int n;
cin>>n;
vector<pair<ll,int> > a(n); // (token, index)
for(int i=0;i<n;i++) {
cin>>a[i].first;
a[i].second=i;
}
sort(a.begin(),a.end());
vector<int> c(n,1); // check
int l=0, r=n-1;
while(l<=r) {
int mid=(l+r)/2;
ll psum=0; // mid이전 플레이어들의 토큰을 모두 먹는다
for(int i=0;i<=mid;i++) psum+=a[i].first;
bool fail=false;
for(int i=mid+1;i<n;i++) {
if(psum<a[i].first) { // 이길 수 없다면
fail=true;
break;
}
else psum+=a[i].first; // 다음 플레이어를 이기면 토큰 흡수
}
if(!fail) r=mid-1;
else {
for(int i=0;i<=mid;i++) c[i]=0; // mid이전 플레이어들은 모두 불가능
l=mid+1;
}
}
vector<int> res;
for(int i=0;i<n;i++) {
if(c[i]) res.push_back(a[i].second+1);
}
sort(res.begin(),res.end());
cout<<res.size()<<endl;
for(int i=0;i<res.size();i++) cout<<res[i]<<' ';
cout<<endl;
return;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;
cin>>t;
while(t--) {
solve();
}
return 0;
}
Comments