Codeforces Round #787 (Div. 3)个人题解

Codeforces Round #787 (Div. 3)个人题解

A. Food for Animals

题目大意

a a a 包狗粮, b b b 包猫粮, c c c 包通用, x x x 只狗和 y y y 只猫,问你能不能让所有的猫和狗都吃到东西。

思路

先让狗吃狗粮,猫吃猫粮,统计一下还有多少只猫狗没有吃到东西,如果 c c c 比剩下的猫狗数量多输出Yes,否则输出No

参考代码

bool solve(){
   
    int a,b,c,x,y;cin>>a>>b>>c>>x>>y;
    x-=a, y-=b;
    x=max(x,0), y=max(0,y);
    return x+y<=c;
}
int main(){
   
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    
    int _;cin>>_;
    while(_--){
   
        cout<< (solve()?"Yes":"No") <<endl;
    }
    
    return 0;
}

B. Make It Increasing

题目大意

给定一个长度为 n n n 的数组,一次操作将一个元素变成其下取整。求将数组变为严格递增所需要的最小操作数。

思路

从后往前贪心,如果当前元素的值大于等于右边一个元素,将该元素变为下取整直到比右边元素小,若该元素已经是0了,说明无解。

因为数组中每个元素最大值为 2 e 9 2e9 2e9 ,每个元素最多下取整31次,时间复杂度可以保证。

参考代码

int a[N];

void solve(){
   
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=0;
    for(int i=n-1;i>=1;i--){
   
        while(a[i] && a[i]>=a[i+1]) a[i]/=2, ans++;
        if(a[i]>=a[i+1]){
   
            cout<<-1<<endl;
            return ;
        }
    }
    cout<<ans<<endl;
}

C. Detective Task

题目大意

思路

最后一个出现的1和第一个出现的0以及中间的字串都是可疑的。注意判断边界。

参考代码

int a[N];

void solve(){
   
    string s;cin>>s;
    if(s.length()==1){
   
        cout<<1<<endl;
        return ;
    }
    int t=-1;
    for(int i=0;s[i];i++){
   
        if(s[i]=='1') t=i;
        if(s[i]=='0'){
   
            if(t!=-1) cout<<i-t+1<<endl;
            else cout<<i-t<<endl;
            return;
        }
    }
    if(t==-1) cout<<s.length()<<endl;
    else cout<<s.length()-t<<endl;
}

D. Vertical Paths

题目大意

给定一棵树,求最大路径条数。

思路

将每个节点染色,保证每个父节点和最多一个子节点的颜色是相同的,为其他子节点染上一个新颜色。

参考代码

int col[N];
vector<int> g[N];
int now=1;
vector<int> ans[N];

// 为节点u染上颜色x
void dfs(int u,int x){
   
    ans[x].push_back(u);
    col[u]=x;
    bool f=0;// 有没有子节点颜色与u相同
    for(auto v:g[u]){
   
        if(!f){
   
            dfs(v,x);
            f=1;
        }
        else{
   
            // 染上新颜色
            now++;
            dfs(v,now);
        }
    }
}

void solve(){
   
    int n;cin>>n;
    for(int i=1;i<=n;i++) g[i].clear(), col[i]=0, ans[i].clear();
    int root;
    // 建图并找出根节点
    for(int i=1;i<=n;i++){
   
        int x;cin>>x;
        if(i==x) root=x;
        else g[x].push_back(i);
    }
    now=1;// 现在用了几种颜色
    dfs(root,1);
    cout<<now<<endl;
    for(int i=1;i<=now;i++){
   
        cout<<ans[i].size()<<endl;
        for(auto x:ans[i]) cout<<x<<" ";
        cout<<endl;
    }
    cout<<endl;
}

E. Replace With the Previous, Minimize

题目大意

给一个长度为 n n n 的字符串,最多可以进行 m m m 次操作,具体操作为选择某个字母,如果该字母在该字符串中出现过,则将字符串中的该字符变为字母表的前一个字母(‘a’变为’z’)。求可转化为的字典序最小的字符串。

思路

要求字典序最小,从左往右贪心,尽量将该字符减小到 a a a。但是我们考虑这个例子:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值