Codeforces Round #229 (Div. 2)C - Inna and Candy Boxes心得

题目链接:http://codeforces.com/contest/390/problem/C

思路:

刚开始在构思这个题时,思路十分幼稚,就是按照题目的要求,进行多次的搜索,毫无疑问得到Tl的结果。之后又进行了一些很简单的优化,最后得到了一个复杂度为n*w的算法,还是不行。十分困惑,到网上看了一些题解,才知道应该用预处理的方法来进行优化,仔细思索了一番感觉豁然开朗。

具体方法:

设X=l~r区间中“1”的个数,Y=l~r区间中指定位置中“1”的个数,Z=l~r区间中指定位置的个数。

所以,最后的结果应该等于X+Z-2*Y;

其中可以用一个数组a[],来记录每个下标之前“1”的个数,比如a[i]=1~i中“1”的个数,所以X=a[r]-a[l-1]。

Z=(r+1-l)/k;

Y的计算可能不太好理解,因为指定位置%k相等,所以可以设数组b[][],b[i%k][i]表示1~i中,模k等于i%k的数中“1”的个数,所以

Y=b[r%k][r]-[r%k][l-1];

具体请看代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <bitset>
#include <complex>
#include <cmath>
#include <ctime>
#include <cassert>

using namespace std;
#define SIZE 100005
int a[SIZE]={0},b[10][SIZE]={0};//这是两个记录数组,别忘了初始化为零
char c[SIZE];
int main()
{
    int n,k,w;
    scanf("%d%d%d",&n,&k,&w);
    scanf("%s",c);
    //初始化1~k 为递推做准备
    for (int i=1;i<=k;i++){
        b[i%k][i]=c[i-1]-'0';
        a[i]+=a[i-1]+c[i-1]-'0';
    }
    for (int i=k+1;i<=n;i++){
        a[i]+=a[i-1]+c[i-1]-'0';
        //用递推计算b[i%k][i]
        if (c[i-1]=='0') b[i%k][i]+=b[i%k][i-k];
        else b[i%k][i]+=b[i%k][i-k]+1;
    }
    while(w--){
        int l,r,re;
        scanf("%d%d",&l,&r);
        re=(a[r]-a[l-1])+(r+1-l)/k-2*(b[r%k][r]-b[r%k][l-1]);  //注意细节r%k=(l-1)%k 被减数的下标应该是l-1
        printf("%d\n",re);
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值