zoukankan      html  css  js  c++  java
  • CF1415C Bouncing Ball 题解

    题意分析

    给出一个由 $0,1$ 组成的序列,要从第 $p$ 个位置开始,每次跳 $k$ 个单位,要求跳出序列,只有当所有经过的位置都为 $1$ 才合法。你可以花费 $x$ 将这个序列的第一个元素删除,也可以花费 $y$ 将其中一个位置改为 $1$ ,求能合法跳出序列的最小修改花费。

    思路分析

    发现当第一个位置确定后,后面的所有跳到的位置都可以确定,考虑枚举删去的元素数量,即起始位置。

    显然前 $p-1$ 个元素都是无用的,可以不管它们,然后设为从第 $1$ 个位置开始。

    假设删去前 $i$ 个元素,那么很容易可以得出需要跳的次数:$left lceil frac{(n-i)}{k} ight ceil$ 。然后需要知道被跳到的地方有多少个位置为 $0$ ,这个可以把整个序列按照对 $k$ 的模数进行分类,然后对于每一类预处理出为 $1$ 的个数,处理的时候再统计当前位置之前的 $1$ 的个数,就可以得出后面的 $0$ 的个数。最后加上删去 $i$ 个元素的花费即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath> 
    using namespace std;
    const int N=1e5+100;
    int T,n,p,k,x,y,ans;
    int cnt[N],ncnt[N];
    string s;
    void clear()
    {
        memset(cnt,0,sizeof(cnt));//整个序列中 1 的个数
        memset(ncnt,0,sizeof(ncnt));//当前位置之前的 1 的个数
        ans=1e9;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            clear();
            scanf("%d%d%d",&n,&p,&k);cin>>s;scanf("%d%d",&x,&y);
            for(int i=p-1;i<n;i++)
                cnt[(i-p+1)%k]+=s[i]-'0';//预处理 1 的个数
            for(int i=p-1;i<n;i++)
                ans=min(ans,((int)ceil((double)(n-i)/k)-cnt[(i-p+1)%k]+ncnt[(i-p+1)%k])*x+(i-p+1)*y),ncnt[(i-p+1)%k]+=s[i]-'0';
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    解决mybatis查询返回结果值串查
    MSSQL Export Excel
    Linux检测硬盘读取速度
    Linux修改用户密码
    Linux系统关闭防火墙端口
    Linux系统查看系统信息
    查找一个String中存储的多个数据
    编辑器vi命令
    去除一段文字最后一个符号
    替换Jar包中的一个文件 Replace a file in a JAR
  • 原文地址:https://www.cnblogs.com/TEoS/p/14084101.html
Copyright © 2011-2022 走看看