Codeforces Round #702 (Div. 3)

A. Dense Array

原题链接


给你一个数组,保证相邻的两数大的值不能超过小的值两倍。如果超过了,我们就必须在他们之间添加一些数保证整个序列符合上述条件,求添加的最少的数多少个。

模拟即可,如果max(a[i],a[i+1])>min(a[i],a[i+1])。那就在中间添加符合要求的即可。

#include <bits/stdc++.h>

using namespace std;
const int N=1e3+5;
int a[55];
void solve()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        int res=0,last=a[1];
        for(int i=2;i<=n;i++){
            if(a[i]>last){
                if(a[i]<=last*2){
                    last=a[i];continue;
                }else{
                    while(a[i]>last*2){
                        res++;last=2*last;
                    }
                }
            }else {
                if(last<=a[i]*2){
                    last=a[i];continue;
                }
                int temp=a[i];
                while(temp*2<last){
                    res++;temp=temp*2;
                }
                last=a[i];
            }
        }
        cout<<res<<'\n';
    }
}
int main() {
    solve();
    return 0;
}

B. Balanced Remainders

原题链接


给你一个数列,然后c0,c1,c2分别表示数列中n%3后的结果填充在c0,c1。c2中。然后你每次都可以对数组中的数进行+1操作,目的就是让c0=c1=c2。求最小操作次数。


模拟,首先求最终达到的平均数n/3。我们每次找(c0,c1,c2)中最大的进行操作,让它减到平均数,相应的他减少的一定会补在下一位上面(看成一个环)。最多走两遍就行。

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=5e4+5;
int a[N];
void solve()
{
    int t;
    cin>>t;
    while(t--){
        int n,cur[3]={};
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];cur[a[i]%3]++;
        }
        int res=0;
        while(1){
            bool flag=true;
            if(cur[0]!=n/3&&cur[0]>n/3){
                int ad=cur[0]-n/3;
                res+=ad;
                cur[0]=n/3;
                cur[1]+=ad;
                flag=false;
            }
            if(cur[1]!=n/3&&cur[1]>n/3){
                int ad=cur[1]-n/3;
                res+=ad;
                cur[1]=n/3;
                cur[2]+=ad;
                flag=false;
            }
            if(cur[2]!=n/3&&cur[2]>n/3){
                int ad=cur[2]-n/3;
                res+=ad;
                cur[2]=n/3;
                cur[0]+=ad;
                flag=false;
            }
            if(flag)break;
        }
        cout<<res<<'\n';
    }
}
int main() {
    solve();
    return 0;
}

C. Sum of Cubes

原题链接


a 3 + b 3 = x a^3+b^3=x a3+b3=x给你x,问是否能找到这样的a和b(x<=1e12)


做法1:我们先枚举一个a,另外的b通过二分来求。O(n*logn,n=1e4)可做。

做法2:我们事先把(1~n)的三次方放到一个集合里,每次枚举i,寻找是否存在x-i*i*i。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e3+5;
void solve()
{
    int t;
    cin>>t;
    while(t--){
        ll x;
        cin>>x;
        int flag=0;
        for(int i=1;i<=10000;i++){
            ll t=x-1ll*i*i*i;
            ll b,l=1,r=10000;
            while(l<=r){
                ll mid=l+r>>1;
                if(mid*mid*mid>=t){
                    b=mid;r=mid-1;
                }else l=mid+1;
            }
            if(1ll*i*i*i+b*b*b==x){
                cout<<"YES";flag=1;break;
            }
        }
        if(!flag)cout<<"NO";
        cout<<'\n';
    }
}
int main() {
    solve();
    return 0;
}

D. Permutation Transformation

原题链接


大佬说这是笛卡尔数,菜鸡dfs写了。模拟

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e3+5;
int a[N],ans[N];
void dfs(int l,int r,int cnt)
{
    if(l>r)return ;
    int pos,maxx=0;
    for(int i=l;i<=r;i++){
        if(a[i]>maxx){
            pos=i;maxx=a[i];
        }
    }
    ans[pos]=cnt;
    dfs(l,pos-1,cnt+1);
    dfs(pos+1,r,cnt+1);
}
void solve()
{
    int t;
    cin>>t;
    while(t--){
        int n,pos=-1;
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];if(a[i]==n)pos=i;
        }
        ans[pos]=0;
        dfs(0,pos-1,1);
        dfs(pos+1,n-1,1);
        for(int i=0;i<n;i++)cout<<ans[i]<<' ';
        cout<<'\n';
    }
}
int main() {
    solve();
    return 0;
}

E. Accidental Victory

原题链接


给一个序列,每次选择两个数进行PK,大的能够获胜并吞并小的分数,数组长度-1,继续选择两个数进行PK。其中分数相同的人随机选择一个人获胜,最后求有多少个下标这样的数能赢到最后。


要想获胜分数肯定不能是最小的一开始,首先就是排序,因为排好序后,最后一个人肯定能站到最后,除此之外倒数第二个相对于前n-1也一定能占到最后,但是它拿到前n-2个人的分数后,必须保证>a[n]才能够真正的站到最后。以此类推。那我们就从后往前枚举保证sum[i]>=a[i+1]。否则i包括他之前的人都不可能占到最后。

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=3e5+5;
struct node{
    int val,sum,flag;
}a[N];
bool cmp(node a,node b)
{
    return a.val<=b.val;
}
void solve()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i].val);
        }
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++){
            if(i==1)a[i].sum=a[i].val;
            if(i>1)a[i].sum=a[i-1].sum+a[i].val;
        }
        int res=1;
        if(n==1){
           printf("1\n%d\n",a[1].val);
        }else{
            // for(int i=1;i<=n;i++)cout<<a[i].val<<' ';
            // cout<<'\n';
            a[n].flag=1;
            for(int i=n-1;i>=1;i--){
                if(a[i].sum>=a[i+1].val){
                    a[i].flag=1;res++;
                }else if(i==1&&a[i].val==a[i+1].val)
                    a[i].flag=1,res++;
                 else break;   
            }
            printf("%d\n",res);
            for(int i=1;i<=n;i++){
                if(a[i].flag==1)printf("%d ",a[i].val);
            }
        }
    }
}
int main() {
    solve();
    return 0;
}

F. Equalize the Array

原题链接


给你一个数列,通过删除一些数保证他们出现的次数一样多0或者c个。


先把他们各自出现的次数统计出来。例如1 3 2 1 4 2。出现的次数2 2 1 1。然后删除一些让他们出现次数一样。我们先把他们从大到小排个序,然后枚举每个数。对每个数来说,我们假定最终的cur=a[i]。那左边都是>=。只需要删除多的就行l[i]-a[i]*i。右边都是<=那全删除即可r[i+1]求最小值即可

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll l[N],r[N];
void solve()
{
    int t;
    cin>>t;
    while(t--){
        int n,x;
        cin>>n;
        map<int,int>mp;
        for(int i=0;i<n;i++){
            cin>>x;
            mp[x]++;
        }
        vector<int>a;
        for(auto it:mp){
            a.pb(it.second);
        }
        sort(a.begin(),a.end(),greater<int>());
        l[0]=r[a.size()+1]=0;
        for(int i=0;i<a.size();i++)l[i+1]=a[i]+l[i];
        for(int i=a.size()-1;i>=0;i--)r[i+1]=r[i+2]+a[i];
//        int nn=a.size();
//        for(int i=0;i<nn;i++)cout<<a[i]<<' ';
//        cout<<'\n';
//        for(int i=1;i<=nn;i++)cout<<l[i]<<' ';
//        cout<<'\n';
//        for(int i=1;i<=nn;i++)cout<<r[i]<<' ';
//        cout<<'\n';
        ll res=INF;
        for(int i=0;i<a.size();i++){
            res=min(res,l[i+1]+r[i+2]-1ll*(i+1)*a[i]);
        }
        cout<<res<<'\n';
    }
}
int main() {
    solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值