Codeforces Round #702 (Div. 3)

Codeforces Round #702 (Div. 3)

https://codeforces.ml/contest/1490

A. Dense Array

思路

水题,直接遍历一遍求出相邻两个数之间最少需要添加几个数即可。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 1e5+7;
const ll mod = 1e9+7;       

int a[57];

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        int n;
        cin>>n;
        for (int i = 0; i < n; ++i)
        {
            cin>>a[i];
        }
        int ans=0;
        for (int i = 1; i < n; ++i)
        {
            int x=max(a[i],a[i-1]),y=min(a[i],a[i-1]);
            if(x<=2*y)continue;
            while(x>2*y){
                y*=2;
                ans++;
            }
        }cout<<ans<<endl;
    }
    return 0;
}

B. Balanced Remainders

思路

首先求出c0、c1、c2的最终结果(n/3)。
优先考虑最优情况,

  • 当c0小于k时,使用c2来补充是最优情况,而使用c1来补充则需要乘以2.
  • c1、c2同理。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 3e4+7;
const ll mod = 1e9+7;       
int a[N];
int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        int n;
        cin>>n;
        int c[4]={0};
        for (int i = 0; i < n; ++i)
        {
            int x;
            cin>>x;
            c[x%3]++;
        }int k=n/3,ans=0;
        for (int i = 0; i < 3; ++i)
        {
            if(c[i]>=k)continue;
            if(i==0){
                if(c[2]>=k){
                    int p=min(k-c[0],c[2]-k);
                    ans+=p;
                    c[0]+=p;
                    c[2]-=p;
                }
                if(c[0]<k){
                    c[1]-=k-c[0];
                    ans+=2*(k-c[0]);
                    c[0]=k;
                }
            }
            else if(i==1){
                if(c[0]>=k){
                    int p=min(c[0]-k,k-c[1]);
                    ans+=p;
                    c[1]+=p;
                    c[0]-=p;
                }
                if(c[1]<k){
                    c[2]-=k-c[1];
                    ans+=2*(k-c[1]);
                    c[1]=k;
                }
            }
            else{
                if(c[1]>=k){
                    int p=min(c[1]-k,k-c[2]);
                    c[2]+=p;
                    c[1]-=p;
                    ans+=p;
                }
                if(c[2]<k){
                    c[0]-=k-c[2];
                    ans+=2*(k-c[2]);
                    c[2]=k;
                }
            }
        }cout<<ans<<endl;
    }
    return 0;
}

C. Sum of Cubes

思路

预处理出1e12内所有立方根,对于每个x暴力搜索判断即可。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 1e5+7;
const ll mod = 1e9+7;       

int main(){ 
    IO;
    map<ll,int>mp;
    for (ll i = 1; i*i*i <= 1e12; ++i)
    {
        mp[i*i*i]=1;
    }
    int t=1;
    cin>>t;
    while(t--){  
        ll x;
        cin>>x;
        int flag=0;
        for (ll i = 1; i*i*i <= x; ++i)
        {
            if(x-i*i*i<=0)break;
            if(mp[x-i*i*i]){
                flag=1;break;
            }
        }if(flag)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

D. Permutation Transformation

思路

类似于二叉树的递归创建。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 1e5+7;
const ll mod = 1e9+7;       

int a[107],d[107];

void slove(int l,int r,int dd)
{
    if(l>r)return ;
    int mid,maxn=0;
    for (int i = l; i <= r; ++i)
    {
        if(maxn<a[i]){
            mid=i;
            maxn=a[i];
        }
    }
    d[mid]=dd;
    slove(l,mid-1,dd+1);
    slove(mid+1,r,dd+1);
}

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        int n;
        cin>>n;
        for (int i = 1; i <= n; ++i)
        {
            cin>>a[i];
        }
        slove(1,n,0);
        for (int i = 1; i <= n; ++i)
        {
            cout<<d[i]<<" ";
        }cout<<endl;
    }
    return 0;
}

E. Accidental Victory

思路

排序后求出前缀和,从后往前找到第一个当前位置的前缀和小于后一位置的值,此位置后的值都满足条件,最后输出它们的编号即可(注意判断两个玩家的值相同的情况)。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 2e5+7;
const ll mod = 1e9+7;       

struct $
{
ll x;
int id;
bool operator <($ p)const{
	return x<p.x;
}
}a[N];
ll b[N],sum[N];

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
    	int n;
    	cin>>n;
    	for (int i = 1; i <= n; ++i)
    	{
    		cin>>a[i].x;
    		a[i].id=i;
    	}sort(a+1,a+n+1);
    	map<int,int>mp;
    	for (int i = 1; i <= n; ++i)
    	{
    		sum[i]=sum[i-1]+a[i].x;
    	}mp[a[n].id]=1;
    	int i;
    	for (i = n-1; i > 0; --i)
    	{
    		if(sum[i]<a[i+1].x)break;
    		mp[a[i].id]=1;
    	}
    	for (int i = 1; i <= n; )
    	{
    		int j=i;
    		int flag=0;
    		while(a[j].x==a[i].x&&j<=n){
    			if(mp[a[j].id]){
    				flag=1;
    				break;
    			}j++;
    		}
    		if(flag){
    			j=i;
	    		while(a[j].x==a[i].x&&j<=n){
	    			mp[a[j].id]=1;
	    			j++;
	    		}
	    	}
    		i=j;
    	}int ans=0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if(mp[i])ans++;
    	}cout<<ans<<endl;
    	for (int i = 1; i <= n; ++i)
    	{
    		if(mp[i])cout<<i<<" ";
    	}cout<<endl;
    }
    return 0;
}

F. Equalize the Array

思路

题意为找出最小的删除数使得删除后的序列满足其中每个数字出现的次数相同。
将每个数字的出现次数记录,并排序,如果想要留下的数字尽量多,就需要保证出现次数多的数字尽可能多的留下。
所以从后往前遍历,考虑每个位置的出现次数是否为最佳情况,求出最优解。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 2e5+7;
const ll mod = 1e9+7;       

ll a[N];
int n;
vector<int>v;

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        cin>>n;
        v.clear(); 
        int l=0,r=n;
        for (int i = 1; i <= n; ++i)
        {
            cin>>a[i]; 
        }
        sort(a+1,a+n+1);
        int cnt=0,x=a[1];
        for (int i = 1; i <= n; ++i)
        {
            if(x==a[i])cnt++;
            else v.push_back(cnt),cnt=1,x=a[i];
        }v.push_back(cnt);
        sort(v.begin(),v.end());
        int sum=0;
        map<int,int>mp;
        for (int i : v)
        {
            mp[i]++;
        }
        int ans=n+1;
        for (int i = n; i > 0; --i)
        {
            if(mp[i]==0)continue;
            ans=min(ans,n-i*(mp[i]+sum));
            sum+=mp[i];
        }cout<<ans<<endl;
    }
    return 0;
}

G. Old Floppy Drive

思路

再次看错题了,看成了等于x,最后没做出来
求出序列的前缀和,并记录每个前缀和的位置,并且找到所有位置中前缀和最大的值。
对于x,

  • 如果sum[n]<=0并且x>max{sum[i]},则此时无解。
  • 找到需要的最小轮数(从1走到n),二分查找第一个大于等于其剩余值的位置即可。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 2e5+7;
const ll mod = 1e9+7;       

ll a[N],sum[N],mp[N];

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
    	int n,m;
    	cin>>n>>m; 
    	mp[0]=0;
    	for (int i = 1; i <= n; ++i)
    	{
    		cin>>a[i];
    		sum[i]=sum[i-1]+a[i];
    		mp[i]=max(mp[i-1],sum[i]);
    	} 
    	while(m--){
    		ll x;
    		cin>>x;
    		if(sum[n]<=0&&mp[n]<x){
    			cout<<-1<<endl;
    			continue;
    		}
    		ll q=mp[n]<x?(x-mp[n]+sum[n]-1)/sum[n]:0;
    		ll r=lower_bound(mp+1,mp+n+1,x-q*sum[n])-mp-1;
    		cout<<q*n+r<<" ";
    	}cout<<endl;
    }
    return 0;
}
posted @ 2021-02-17 01:15  !^^!  阅读(32)  评论(0编辑  收藏  举报