• Codeforces Round #642 (Div. 3) 题解


    A

    序列是(0,m,0,0,cdots)时有最优解。

    特判一下(n=1,2)的情况。

    int main()
    {
        int T=read();
        while (T--)
        {
            ll n=read(),m=read();
            if (n==1) puts("0");
            else if (n==2) printf("%lld
    ",m);
            else printf("%lld
    ",m*2);
        }
        return 0;
    }
    

    B

    贪心的考虑,每次操作肯定会把(a)中最小的换成(b)中最大的,如果这样做没有收益那么就停下来。

    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();m=read();
            rep(i,1,n) a[i]=read();
            rep(i,1,n) b[i]=read();
            while (m--)
            {
                int id1=1,id2=1;
                rep(i,2,n)
                    if (a[i]<a[id1]) id1=i;
                rep(i,2,n)
                    if (b[i]>b[id2]) id2=i;
                if (a[id1]>b[id2]) break;
                swap(a[id1],b[id2]);
            }
            int ans=0;
            rep(i,1,n) ans+=a[i];
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    C

    所有格子都集中到最中间的那个格子时有最优解。

    枚举一下所需时间再乘一下格子数即可。

    int main()
    {
        int T=read();
        while (T--)
        {
            int n=read();
            unsigned long long ans=0;
            rep(i,1,(n-1)/2)
            {
                ans+=1ll*i*i*2*4;
            }
            printf("%llu
    ",ans);
        }
        return 0;
    }
    

    D

    用个堆维护当前的极长连续(0)区间即可。

    struct node{int l,r;};
    bool operator <(node p,node q)
    {
        if (p.r-p.l!=q.r-q.l) return p.r-p.l<q.r-q.l;
        else return p.l>q.l;
    }
    priority_queue<node> q;
    int n,a[200200];
    
    int calc(int l,int r)
    {
        if ((r-l+1)&1) return (l+r)>>1;
        else return (l+r-1)>>1;
    }
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();
            q.push((node){1,n});
            int id=0;
            while (!q.empty())
            {
                node now=q.top();q.pop();
                int mid=calc(now.l,now.r);
                a[mid]=(++id);
                if (mid-1>=now.l) q.push((node){now.l,mid-1});
                if (mid+1<=now.r) q.push((node){mid+1,now.r});
            }
            rep(i,1,n) printf("%d ",a[i]);puts("");
        }
        return 0;
    }
    

    E

    (可能做复杂了)

    把所有模(k)的余数相同的位置拿出来,那么其它位置首先要变成(0).

    记拿出来的权区间长度为(n),且有(m)(1),其前缀和为(s_i),枚举一下最后为1的区间([l,r]), 那么要求的就是(min(m-(s_r-s_{l-1})+(r-l+1)-(s_r-s_{l-1}))), 即(min(m-2s_r+r+2s_{l-1}-(l-1))).对后面哪个沿途取个(min)即可,注意还要加上当前序列全为(0)时最优的情况。

    int n,m,tot,k,a[1001000],s[1001000],all=0;
    char str[1001000];
    
    int calc(int md)
    {
        m=0;tot=0;
        for (int i=md;i<=n;i+=k)
        {
            a[++tot]=(str[i]=='1');
            m+=a[tot];
        }
        rep(i,1,tot) s[i]=s[i-1]+a[i];
        int now=m,mx=0;
        rep(r,1,tot)
        {
            now=min(now,m-s[r]*2+r+mx);
            mx=min(mx,2*s[r]-r);
        }
        now+=all-m;
        return now;
    }
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();k=read();
            scanf("%s",str+1);
            int ans=n;all=0;
            rep(i,1,n) all+=(str[i]=='1');
            rep(i,1,min(n,k)) ans=min(ans,calc(i));
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    F

    一个显然的性质是如果(a_{1,1})的值被确定了,那么沿途中每个位置的值都是确定的,即(a_{i,j}=a_{1,1}+i+j-2).

    同时注意到如果最终的合法路径每个格子都被操作了至少一次,那么我们可以整体减少一次操作使其更优。

    综合上面两个结论,就会发现最终(a_{1,1})的取值只会有(O(nm))个,枚举这个值然后跑dp就行了。

    int n,m;
    ll a[110][110],f[110][110];
    
    ll work(ll st)
    {
        rep(i,0,n) rep(j,0,m) f[i][j]=1e18;
        if (a[1][1]>=st) f[1][1]=a[1][1]-st;
        rep(i,1,n) rep(j,1,m)
        {
            if ((i==1) && (j==1)) continue;
            if (a[i][j]>=(st+i+j-2))
            {
                ll now=a[i][j]-(st+i+j-2);
                f[i][j]=min(f[i-1][j],f[i][j-1])+now;
            }
        }
        return f[n][m];
    }
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();m=read();
            rep(i,1,n) rep(j,1,m) a[i][j]=readll();
            ll ans=4e18;
            rep(i,1,n) rep(j,1,m) ans=min(work(a[i][j]-(i+j-2)),ans);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    【Web技术】561- 网站性能优化之度量篇
    【拓展】什么是Deno?跟Node.js有何区别?
    【Web技术】560- 一个简洁、有趣的无限下拉方案
    【Web技术】559- 一文带你彻底搞懂跨域
    【TS】558- 5000 多字,让你一文掌握 TS 枚举
    【拓展】你真的会写 Markdown 么?
    【调试】557- 11 个Chrome骚技巧让你为所欲为
    ios 地图
    ios 7 20像素解决
    保存图片到相册
  • 原文地址:https://www.cnblogs.com/encodetalker/p/12892458.html
Copyright © 2020-2023  润新知