Codeforces Round #540 (Div. 3)总结

A. Water Buying

题意:给q个询问,每个询问给出3个数字,n,a,b,a是买一升水的花费,b是买2升水的花费,求买n升水的最小花费。

思路:对于每个询问,我们比较2*a和b的大小,如果2*a比b小的话就一直买1升水就行了,否则若n是偶数,全买2升水,若n是奇数,先买一桶一升水的,剩下的全买两升水的,事实上题目里面没有规定a一定比b小,但数据里面似乎是这样的,更严谨的话就应该判断a是否大于b然后看是一升水的要不要买。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=1e3+9;
//int a[maxn],b[maxn];
int main(){
    int i,j,k,n,t;
    cin>>t;
    for(i=1;i<=t;i++){
        ll n,a,b;
        cin>>n>>a>>b;
        if(a*2<=b){
            ll ans=a*n;
            cout<<ans<<endl;
        }
        else{
            ll ans=(n/2)*b+(n-n/2*2)*a;
            cout<<ans<<endl;
        }
    }
}

B. Tanya and Candies

题意:先删去序列里的一个数,然后看奇数位置的数之和是否和偶数位置的数之和相等,若相等,这个删去的数是好的,问有几个这样的good数

思路:统计每个位置偶数位置的数的前缀和,奇数位置的前缀和,很容易能够发现删去一个数之后,这个数之后的数的位置,奇变偶,偶变奇,那么此时偶数位置的数之和就等于eve[i-1]+odd[n]-odd[i],奇数位置的数之和就等于odd[i-1]+eve[n]-eve[i],我们判断他们是否相等就行了

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=2e5+9;
ll a[maxn],odd[maxn],eve[maxn];
int main(){
    int i,j,k,n;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
        if(i%2==1){
            eve[i]=eve[i-1];
            odd[i]=odd[i-1]+a[i];
        }
        else{
            odd[i]=odd[i-1];
            eve[i]=eve[i-1]+a[i];
        }
    }
    ll ans=0;
    for(i=1;i<=n;i++){
        int ODD=0,EVE=0;
        ODD=odd[i-1]+eve[n]-eve[i];
        EVE=eve[i-1]+odd[n]-odd[i];
        if(ODD==EVE){
            ans++;
        }
    }
    cout<<ans<<endl;
}

C. Palindromic Matrix

题意:给你n*n个数,让你构造一个矩阵,这个矩阵左右对称,上下对称

思路:对于n是偶数的情况,我们能够发现每个数出现的次数必须是4的倍数才能构造这样的矩阵,我们开个map储存一下每个数出现的次数,只用处理左上角那四分之一部分,其余的对称就行了,对于这一部分的每个位置,遍历所有出现过的数,如果mp[x]>=4,把x放在这个位置,然后mp[x]-=4;然后n是奇数的情况,中间一行和中间一列的数mp[x]>=2就行了(最中间位置的数出现次数大于等于1就行),然后也是类似的解决方法。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=1e3+9;
int a[maxn],p[maxn][maxn];
map<long long ,int>mp;
int main(){
    int i,j,k,n;
    cin>>n;
    for(i=1;i<=n*n;i++){
        cin>>a[i];
        mp[a[i]]++;
    }
    int _1cnt=0,_2cnt=0;
    for(auto it:mp){
       int x=it.second;
       if(n%2==0){
        if(x%4!=0){
            cout<<"NO"<<endl;
            return 0;
        }
       }
       else{
        if(x%4!=0){
            if(x%2==0){
                _2cnt++;
            }
            else if(x%2==1){
                _1cnt++;
            }
            if(_1cnt>1||_2cnt>(n/2)*2){
                cout<<"NO"<<endl;
                return 0;
            }
        }
       }
    }
    cout<<"YES"<<endl;
    if(n%2==0){
        for(i=1;i<=n/2;i++){
            for(j=1;j<=n/2;j++){
                for(auto it:mp){

                    int x=it.second,y=it.first;
                    if(x>=4&&x%4==0){//cout<<y<<endl;
                        p[i][j]=y;
                        mp[y]-=4;
                        break;
                    }
                }
                p[i][n-j+1]=p[i][j];
                p[n-i+1][j]=p[i][j];
                p[n-i+1][n-j+1]=p[i][j];
            }
        }
    }
    else{
        for(auto it:mp){
            int x=it.second;
            if(x%2)p[n/2+1][n/2+1]=it.first;
        }
        for(i=1;i<=n/2;i++){
            for(j=1;j<=n/2;j++){
                for(auto it:mp){
                    int x=it.second,y=it.first;
                    if(x>=4){
                        p[i][j]=y;
                        mp[y]-=4;
                        break;
                    }
                }
                p[i][n-j+1]=p[i][j];
                p[n-i+1][j]=p[i][j];
                p[n-i+1][n-j+1]=p[i][j];
            }
        }
        for(i=1;i<=n/2;i++){
            if(i==n/2+1)continue;
            for(auto it:mp){
                int x=it.second,y=it.first;
                if(x>=2){
                    p[i][n/2+1]=y;
                    mp[y]-=2;
                   // cout<<mp[y]<<"sfsaf"<<y<<endl;
                    break;
                }
            }
            p[n-i+1][n/2+1]=p[i][n/2+1];
        }
        for(j=1;j<=n/2;j++){
            if(j==n/2+1)continue;
            for(auto it:mp){
                int x=it.second,y=it.first;
                if(x>=2){
                   // cout<<123<<endl;
                    p[n/2+1][j]=y;
                    mp[y]-=2;
                    break;
                }
            }
            p[n/2+1][n-j+1]=p[n/2+1][j];
        }
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            cout<<p[i][j]<<' ';
        }
        cout<<endl;
    }
}

D1. Coffee and Coursework (Easy version)

题意:给你n杯咖啡和你需要完成的作业的页数m,如果一杯咖啡是一天中的第一杯,那么可以写ai页,如果是第二杯,可以写max(0,ai-1)页,第三杯可以写max(0,ai-2)页.......,问最少需要几天可以把作业写完

思路:先对咖啡从大到小排序,然后枚举天数,按题意暴力相加,看值的和是否大于等于m,如果是的话,就更新答案。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=1e2+9;
int a[maxn];
bool cmp(int a,int b){
    return a>b;
}
int main(){
    int i,j,k,n,m;
    cin>>n>>m;
    int sum=0;
    for(i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    if(sum<m){
        cout<<-1<<endl;
        return 0;
    }
    else{
        int ans=inf;
        for(k=n;k>=1;k--){
            sum=0;
            sort(a+1,a+n+1,cmp);
            for(i=1;i<=k;i++){
                sum+=a[i];
            }
            for(i=k+1;i<=n;i++){
                sum+=max(0,a[i]-(i-1)/(k));
            }
            if(sum>=m){
                //cout<<sum<<"sfsf"<<k<<endl;
                ans=min(ans,k);
            }
        }
        cout<<ans<<endl;
    }
}

D2. Coffee and Coursework (Hard Version)

题意:这道题和D1的题意是一样的,就是数据范围不一样

思路:大致思路一样,不过由于数据范围增大,我们需要通过二分找完成作业的天数。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=2e5+9;
ll a[maxn],n;
bool cmp(int a,int b){
    return a>b;
}
ll solve(int k){
        ll sum=0;
        for(ll i=1;i<=k;i++){
            sum+=a[i];
        }
        for(ll i=k+1;i<=n;i++){
            sum+=max((long long)0,a[i]-(i-1)/(k));
        }
        return sum;
}
int main(){
    ll i,j,k,m;
    cin>>n>>m;
    ll sum=0;
    for(i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    if(sum<m){
        cout<<-1<<endl;
        return 0;
    }
    else{
        ll ans=1e18;
        sort(a+1,a+n+1,cmp);
        ll l=1,r=n;
        while(l<r){
            int mid=(l+r)>>1;
            if(solve(mid)>=m){
                r=mid;
            }
            else{
                l=mid+1;
            }
        }
       // cout<<solve(4)<<"sfs"<<endl;
        cout<<r<<endl;
    }

E. Yet Another Ball Problem

题意:略

思路:构成成回文的形式就行了,最多有k*(k-1)对。

F1. Tree Cutting (Easy Version)

题意:给你一颗n个点的树,一些点是红色的,一些点是蓝色的,还要一些点是无色的,要你找出有多少条边拆去之后形成的两颗树,一颗树只存在红色点和无色点,一棵树只存在蓝色点和无色点。

思路:用dfs遍历整棵树,如果一个节点形成的子树包含所有的红色节点并且没有蓝色节点,则ans++。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
int a[maxn],ans=0,r_ct=0,b_ct=0,_rd[maxn],_bl[maxn];
vector<int>vec[maxn];
void dfs(int v,int pre){
    if(a[v]==1)_rd[v]++;
    if(a[v]==2)_bl[v]++;
    for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i];
        if(u==pre)continue;
        dfs(u,v);
        _rd[v]+=_rd[u];
        _bl[v]+=_bl[u];
    }
    if((_rd[v]==r_ct&&_bl[v]==0)||(_bl[v]==b_ct&&_rd[v]==0))ans++;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k,n;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]==1)r_ct++;
        if(a[i]==2)b_ct++;
    }
    for(i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    dfs(1,0);
    cout<<ans<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值