• Codeforces Round #540 (Div. 3) 部分题解


    Codeforces Round #540 (Div. 3)

    题目链接:https://codeforces.com/contest/1118

    题目太多啦,解释题意都花很多时间...还有事情要做,就选一些题来写吧。

    B. Tanya and Candies

    题意:

    在n个数中任意删去一个,如果这个数被删去后,剩余数的奇数和以及偶数和相等,那么就定义这个数为"好数"。现在问这n个数中有多少个“好数”。

    题解:

    预处理出奇数前缀和、偶数前缀和,删去一个数后所有的奇数位置和 就为前面的奇数和以及后面的偶数和。然后枚举+判断就行了。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n;
    int a[N];
    ll pre[N],sub[N];
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        ll sum1=0,sum2=0;
        for(int i=1;i<=n;i++){
            pre[i]=pre[i-1];
            sub[i]=sub[i-1];
            if(i&1) pre[i]+=a[i];
            else sub[i]+=a[i];
        }
        sum1=pre[n];sum2=sub[n];
        ll sum=sum1+sum2;
        ll ans = 0;
        for(int i=1;i<=n;i++){
            ll now =0;
            if(i&1){
                now+=pre[i-1];
                now+=sum-sub[i-1]-sum1;
            }else{
                now+=sub[i-1];
                now+=sum-pre[i-1]-sum2;
            }
            if(now*2==sum-a[i]) ans++;
        }
        cout<<ans;
        return 0;
    }
    View Code

    D2. Coffee and Coursework (Hard Version)

    题意:

    给出n杯咖啡,每杯咖啡能增加工作量ai,同时给出m即最终需要的工作量。

    每一天都可以喝咖啡来增加工作量,但是在同一天中,每多喝一杯咖啡,相应增加的工作量就会多减少1。

    最后问最少需要多少天,才能够完成工作量。

    题解:

    很显然,天数越多,工作越有可能被完成。所以可以二分天数,然后在此基础上,贪心地喝咖啡,也就是说,这x天的第1杯咖啡,都是权值最大的那些;第2杯就是次大的那些...以此类推。

    这个题感觉也不是很难,就是二分+判断可行性,具体见代码吧:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 3e5+5;
    int n,m;
    int a[N];
    int check(int x){
        int i;
        ll sum=0,cnt=0;
        for(i=1;i<=n;i++){
            sum+=a[i]-cnt;
            if(i%x==0) cnt++;
            if(sum>=m) return true;
        }
        return false;
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        reverse(a+1,a+n+1);
        int l=1,r=1e9+1,mid;
        while(l<r){
            mid=l+r>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        if(l==1e9+1) cout<<-1;
        else cout<<l;
        return 0;
    }
    View Code

    F1. Tree Cutting (Easy Version)

    题意:

    给出一颗树,其中有些点被染为颜色1,有些被染为颜色2,还有些没被染色,就是颜色0。现在要求删去一条边,使得树变为两个部分,并且满足每一部分中不同时存在1或者2颜色。

    现在问有多少条边删去后,满足条件。

    题解:

    这个题也不是很难...维护每个结点的cnt1,cnt2,分别表示以它为根的子树中,1颜色和2颜色有多少。

    如果满足一个结点,以它为根的子树中,包含了所有的1或者2颜色,并且不包含另外一种颜色,那么答案就加一。

    一个dfs就搞定了。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 3e5+5;
    int n,sum1,sum2;
    int a[N],cnt1[N],cnt2[N];
    vector <int> g[N];
    int ans;
    void dfs(int u,int fa){
        if(a[u]==1) cnt1[u]++;
        if(a[u]==2) cnt2[u]++;
        for(auto v:g[u]){
            if(v==fa) continue ;
            dfs(v,u);
            cnt1[u]+=cnt1[v];
            cnt2[u]+=cnt2[v];
        }
        if(cnt1[u]==sum1 && !cnt2[u]) ans++;
        if(!cnt1[u] && cnt2[u]==sum2) ans++;
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            if(a[i]==1) sum1++;
            if(a[i]==2) sum2++;
        }
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        dfs(1,-1);
        cout<<ans;
        return 0;
    }
    View Code
  • 相关阅读:
    说说委托是个什么东西,以及委托有什么用
    Fedora/Centos使用dnf/yum为Firefox安装Flash,两行命令超简单
    Debian中的NVIDIA显卡驱动安装——超简单,一行命令
    对象、字段、属性、方法、成员、接口各自含义
    C#中的字段与属性的区别及属性的作用
    C#的foreach遍历循环和隐式类型变量
    依赖注入的通俗讲解,设计低耦合的系统
    群晖moments提示错误代码117的解决方案
    群晖数据库错误解决
    解决终端录制工具asciinema 的错误
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10409172.html
Copyright © 2020-2023  润新知