Codeforces Round #702 (Div. 3) A~F题解

A. Dense Array

  • 解题思路
    我们将这个公式变化一下,实际上就是要求相邻两个数 a i , a i + 1 a_i,a_{i+1} ai,ai+1满足 a i ≤ 2 a i + 1 a_i\leq 2a_{i+1} ai2ai+1或者 a i + 1 ≤ 2 a i a_{i+1}\leq 2a_{i} ai+12ai,所以我们贪心维护这样的条件即可。
  • AC代码
/**
  *@filename:A
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 08:48
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 50 + 5;
const int P = 1e9+7;

int t,n,a[N];
void solve(){
    int cnt = 0;
    for(int i = 2; i <= n; ++ i){
        int temp1 = max(a[i],a[i - 1]) ,temp2 = (min(a[i],a[i - 1]) * 2);
        //维护。
        while(temp1 > temp2){
            cnt ++;
            temp1 = (temp1 + 1) / 2;
        }
    }
    cout << cnt << endl;
}
int main(){
    cin >> t;
    while(t -- ){
        cin >> n;
        for(int i = 1; i <= n; ++ i){
            cin >> a[i];
        }
        solve();
    }
    return 0;
}

B. Balanced Remainders

  • 解题思路
    首先我们需要知道,我们只在意每个数对 3 3 3的余数,所以我们可以分成 0 , 1 , 2 0,1,2 0,1,2三组,而这三组的数量一定要平均,即都为平均值。 一步移动只能从 0 − > 1 , 1 − > 2 , 2 − > 0 0- >1,1->2,2->0 0>1,1>2,2>0,那么根据贪心思想,首先我们处理多出来的部分,遍历将多出来的进行一步移动,由于这次遍历已经处理好了一些情况,所以我们只需统计每组与平均值的差值即可。
  • AC代码
/**
  *@filename:B
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 08:49
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int t,n,a[N],c[3];   
void solve(){
    //从0 - > 1转换1次,从1 - > 2转换1次,从2 - > 0转换一次。
    int avg = (c[0] + c[1] + c[2]) / 3;
    int cnt = 0;
    for(int i = 0; i < 3; ++ i){
        if(c[i] > avg){
            c[(i + 1) % 3] += (c[i] - avg);
            cnt += c[i] - avg;
        }
    }
    for(int i = 0; i < 3; ++ i){
        if(c[i] < avg){
            cnt += avg - c[i];
        }
    }
    cout << cnt << endl;
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        scanf("%d", &n);
        memset(c,0,sizeof(c));
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &a[i]);
            c[a[i] % 3] ++ ;
        }
        solve();
    }
    return 0;
}

C. Sum of Cubes

  • 解题思路
    这道题比较好理解,就是对于 a 3 + b 3 = x 3 a^3+b^3=x^3 a3+b3=x3,已知 x x x,判断是否存在这样的 a , b a,b a,b。我们有两种做法,一种是预处理出所有的立方和, x x x最大为 1 0 12 10^{12} 1012,所以我们只需要处理 1 0 4 10^4 104的数量级,这种很方便。当然我们这里采用的是枚举 a a a,然后二分判断是否存在这样的 b b b即可。效率也很高。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 08:49
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int t;
ll x;
bool pow(ll x){
    ll l = 1,r = sqrt(x);
    while(l < r){
        ll mid = (l + r) >> 1;
        ll temp = mid * mid * mid;
        if(temp > x){
            r = mid - 1;
        }
        else if(temp == x){
            return true;
        }
        else{
            l = mid + 1;
        }
    }
    if(l * l * l == x || r * r * r == x)return true;
    return false;
}
void solve(){
    for(ll i = 1;; ++ i){
        if(i * i * i >= x)break;
        ll j = x - i * i * i;
        if(pow(j)){
            puts("YES");
            return;
        }
    }
    puts("NO");
}
int main(){
    cin >> t;
    while(t -- ){
        cin >> x;
        solve();
    }
    return 0;
}

D. Permutation Transformation

  • 解题思路
    这道题还是比较简单的, 我们先找到树根,再构造左右子树,而找树根即是找所处区间中的最大值。

  • AC代码

/**
  *@filename:D
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 08:49
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100 + 5;
const int P = 1e9+7;

int t,n,a[N];
int root[N];
void dfs(int l,int r,int step){
    int maxx = 0,idx = 0;
    for(int i = l; i <= r; ++ i){
        if(a[i] > maxx){
            maxx = a[i];
            idx = i;
        }
    }
    if(idx != 0){
        root[idx] = step;
        dfs(l,idx - 1,step + 1);
        dfs(idx + 1,r,step + 1);
    }
}
void solve(){
    //先找到树根。
    for(int i = 1; i <= n; ++ i){
        if(a[i] == n){
            root[i] = 0;
           dfs(1,i - 1,1);
           dfs(i + 1,n,1);
            break; 
        }
    }
    for(int i = 1; i <= n; ++ i){
        cout << root[i] << " ";
    }
    cout << endl;
}
int main(){
    cin >> t;
    while(t -- ){
        cin >> n;
        for(int i = 1; i <= n; ++ i){
            cin >> a[i];
        }
        solve();
    }
    return 0;
}

E. Accidental Victory

  • 解题思路
    我们可以对他们的值进行排序。 那么我们如果找到了第一个获胜的人,根据后效性(因为后面的一定能获胜这个人,所以他们也一定有可能是冠军)。 而找到第一个获胜的人,我们则可二分查找,需要注意的是,我们需要及时判断及时更新当前的值。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 12:30
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int N = 200000 + 5;
const int P = 1e9+7;

int t,n;
pii a[N];
ll sum[N];
bool check(int mid){
    ll temp = sum[mid];
    for(int i = mid + 1; i <= n; ++ i){
        if(a[i].first > temp)return false;
        temp += a[i].first;
    }
    return true;
}
void solve(){
    //贪心获取,最小值一定不可以。利用最小值的前缀和。由于具有后效性,所以我们直接找到第一个获胜的人即可。
    sort(a + 1,a + 1 + n);
    for(int i = 1; i <= n; ++ i){
        sum[i] = sum[i - 1] + a[i].first;
    }
    int l = 1,r = n;
    while(l < r){
        int mid = (l + r) >> 1;
        if(check(mid)){
            r = mid;
        }
        else{
            l = mid + 1;
        }
    }
    cout << n - l + 1 << endl;
    vector<int> pos;
    for(int i = l; i <= n; ++ i){
        pos.push_back(a[i].second);
    }
    sort(pos.begin(),pos.end());
    for(auto & x : pos){
        cout << x << ' ';
    }
    cout << endl;
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &a[i].first);
            a[i].second = i;
        }
        solve();
    }
    return 0;
}

F. Equalize the Array

  • 解题思路
    由于数据范围达到 1 e 9 1e9 1e9,且我们并不在意每个数的值,所以我们需要进行离散化存储它们出现的次数,最后对出现次数进行排序且求前缀和便于之后枚举处理。 枚举我们需要删除的数,那么次数少于它的就必须全部清除,次数大于它的就必须降到和它一样,由于已经排过序了,所以我们可以直接利用前缀和处理。
  • AC代码
/**
  *@filename:F
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-06-07 13:16
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 200000 + 5;
const int P = 1e9+7;

int t,n,a[N],cnt[N];
int sum[N];
void solve(){
    int tot = 1;
    sort(a + 1,a + 1 + n);
    int pre = -1;
    for(int i = 1; i <= n; ++ i){
        if(pre == -1)pre = a[i];
        if(a[i] == pre){
            cnt[tot] ++;
        }
        else{
            tot ++;
            pre = a[i];
            cnt[tot] ++;
        }
    }
    sort(cnt + 1,cnt + tot + 1);
    for(int i = 1; i <= tot; ++ i){
        sum[i] = sum[i - 1] + cnt[i];
        //cout << cnt[i] << " ";
    }
    //cout << endl;
    int minn = 0x3f3f3f3f;
    for(int i = 1; i <= tot; ++ i){
        minn = min(minn,sum[i - 1] + (sum[tot] - sum[i]) - (tot - i) * cnt[i]);
    }
    printf("%d\n",minn);
}
int main(){
    scanf("%d", &t);
    while(t -- ){
        scanf("%d", &n);
        memset(cnt,0,sizeof(cnt));
        for(int i = 1; i <= n; ++ i){
            scanf("%d", &a[i]);
        }
        solve();
    }
    return 0;
}
posted @ 2022-03-26 16:48  unique_pursuit  阅读(19)  评论(0)    收藏  举报