• Codeforces Round #513(Div.1+Div.2)


    Codeforces Round #513(Div.1+Div.2)

    闲谈:

      重新写博客的第一场比赛,感觉炸裂,成功被Rose和xgcD飞


    A

    题目:

      给出一段长为n个数字字符串,求出能用里面的字符来构成多少个长度为11且开头字符为8的字符串

    题解:

      直接在n/11和8出现的数量中取min就可以了

    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    char st[110];
    int sum[11];
    int main()
    {
        int n;
        scanf("%d",&n);
        scanf("%s",st+1);
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++) sum[st[i]-'0']++;
        if(sum[8]==0){printf("0
    ");return 0;}
        printf("%d
    ",min(sum[8],n/11));
        return 0;
    }
    A

    B

    题目:

      给出一个数n,要求求出a,b,满足n=a+b,且a的数字和与b的数字和的和最大,求出最大和

    题解:

      直接贪心,让最接近n的...999这样的数作为a,如:n=345,则a就为299,然后将n减去a,得到b,然后再计算数字和,这个数字和一定最大,自行yy

    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    int cnt[21];
    LL bin[21];
    int main()
    {
        LL n;
        scanf("%lld",&n);
        bin[0]=1;
        for(int i=1;i<=13;i++) bin[i]=bin[i-1]*10LL;
        LL x=n;int tot=0;
        while(x!=0){cnt[++tot]=x%10;x/=10;}
        LL ans=0;ans+=cnt[tot]-1+(tot-1)*9;
        n-=bin[tot-1]*LL(cnt[tot])-1;
        tot=0;
        while(n!=0){ans+=n%10;n/=10;}
        printf("%lld
    ",ans);
        return 0;
    }
    B

    C

    题目:

      给出一个长度为n的数组a,和一个长度为m的数组b,和一个变量x

      已知c[i][j]=a[i]*b[j],求出x1,x2,y1,y2满足$sum_{i=x1}^{x2}sum_{j=y1}^{y2}c[i][j]<=x$

      求出最大的(x2-x1+1)*(y2-y1+1)

    题解:

      一开始转换成矩阵还更不会做了,我们会发现得到的满足条件的矩阵实际上是$sum_{i=x1}^{x2}a[i]*sum_{i=y1}^{y2}b[i]$

      然后我们预处理出b数组所有的子段信息,包括子段长度和子段和,存入一个结构体

      按照和从小到大排序,然后用一个数组len保存前i个子段的最大长度

      我们枚举x1,x2,得到$d=sum_{i=x1}^{x2}a[i]$,然后用x/d,二分找最接近x/d而且小于等于x/d的子段和,保存位置,因为我们能满足当前位置的子段,说明也能满足前面位置的子段(因为已经按照和从小到大排序了),那么就直接找到这个位置的len,用(x2-x1+1)*len[二分得到的位置]来更新答案即可

    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    LL a[2100],b[2100],s[2100],sb[2100];
    struct node
    {
        LL d,len;
    }B[4100000];
    bool cmp(node n1,node n2){return n1.d<n2.d;}
    LL Max[4100000];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=a[i]+s[i-1];
        for(int i=1;i<=m;i++) scanf("%lld",&b[i]),sb[i]=sb[i-1]+b[i];
        int tot=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=i;j<=m;j++) B[++tot]=(node){sb[j]-sb[i-1],j-i+1};
        }
        sort(B+1,B+tot+1,cmp);
        for(int i=1;i<=tot;i++) Max[i]=max(Max[i-1],B[i].len);
        LL x;scanf("%lld",&x);
        LL mmax=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                LL d=x/(s[j]-s[i-1]);
                int l=1,r=tot,ans=0;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(B[mid].d<=d) l=mid+1,ans=mid;
                    else r=mid-1;
                }
                mmax=max(mmax,(j-i+1)*Max[ans]);
            }
        }
        printf("%lld
    ",mmax);
        return 0;
    }
    C

    D(*)

    题目:

      有很多张椅子,若干个椅子排成一圈,可以排成多个圈

      有n个人,每个人都要坐一个椅子,而且每个人给出l[i],r[i],表示他坐的位置左边要至少有l[i]个空椅子,右边要至少有r[i]个空椅子

      求出至少要用多少个椅子才能满足这n个人的要求

    题解:

      贪心,将l和r分别从小到大排序,ans+=max(l[i],r[i]),最后加上n就行了

    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    int l[110000],r[110000];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
        sort(l+1,l+n+1);sort(r+1,r+n+1);
        LL ans=0;
        for(int i=1;i<=n;i++) ans+=max(l[i],r[i]);
        ans+=n;
        printf("%lld
    ",ans);
        return 0;
    }
    D

    E(*)

    题目:

      给出一棵n个点的树,两个点之间的距离为(两个点之间的边数+1)/2(向下取整)

      求出所有点对的距离和

    题解:

      树形DP

      s[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点数

      d[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点到i点的距离和

      然后分情况转移就行了

    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    struct node
    {
        int x,y,next;
    }a[410000];int len,last[210000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    LL s[210000][2],d[210000][2],ans[210000];
    //s[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点数
    //d[i][k]表示第i棵子树内(不包括i点),(到i点的边数+1)%2=k的点到i点的距离和 
    void dfs(int x,int fa)
    {
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa) continue;
            dfs(y,x);
            ans[x]+=ans[y];
            ans[x]+=d[x][0]*s[y][1]+d[y][1]*s[x][0];
            ans[x]+=d[x][1]*s[y][0]+d[y][0]*s[x][1];
            ans[x]+=d[x][0]*s[y][0]+d[y][0]*s[x][0];
            ans[x]+=(d[x][1]+s[x][1])*s[y][1]+d[y][1]*s[x][1];
            ans[x]+=d[x][0]+d[x][1]+s[x][1];
            s[x][0]+=s[y][1]+1;
            d[x][0]+=d[y][1]+s[y][1]+1;
            s[x][1]+=s[y][0];
            d[x][1]+=d[y][0];
        }
        ans[x]+=d[x][0]+d[x][1];
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ins(x,y);ins(y,x);
        }
        dfs(1,0);
        printf("%lld
    ",ans[1]);
        return 0;
    }
    E
  • 相关阅读:
    H5系列之drag拖放
    H5系列之contenteditable
    H5系列之新input
    利用css3和js实现旋转木马图片小demo
    利用css3实现照片列表展开小demo
    reduce()、filter()、map()、some()、every()、...展开属性
    ES6,ES7,ES8,ES9,ES10新特性
    Web Components 是什么?它为什么对我们这么重要?
    vscode常用快捷键以及插件
    使用for..in时会遍历对象原型中的自定义属性
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9744217.html
Copyright © 2020-2023  润新知