题目链接:http://codeforces.com/contest/390/problem/C
题意:题目大意:输入n,k,w,然后给出n个礼物盒的情况,‘1’表示盒子内有糖果,‘0’表示没有,然后给出w次询问,每次询问将[l,r]区间变成标准情况需要几步,标准情况即l-1+k,l-1+2k....的盒子有糖果,其他在该区间上的盒子没有糖果。
思路:一开始想l-1+k,l-1+2k....这样判断下去,但是1e5显然会超时,因此为了优化,我们需要预处理一下以1-k为开头的结果数,dp[i][j]表示说以i为开头,区间[i,j]需要几步。对于任意的[l,r],结果与dp[l%k][r]-dp[l%k][l]+sol(l)一致,l需要特判一下。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int n, k, w;
char str[N]; //dp[i][j]表示说以i为开头,区间[i+1,j]需要几步
int dp[15][N];
int sol(int x)
{
if (k == 1)
{
if (str[x-1] == '0') return 1;
}
else
{
if (str[x-1] == '1') return 1;
}
return 0;
}
int main()
{
scanf("%d%d%d%s", &n, &k, &w,str);
int len = strlen(str);
memset(dp, 0, sizeof(dp));
for(int i = 0; i < k ; i++)
{
for(int j = i+1; j <= len ; j++)
{
dp[i][j] = dp[i][j-1];
if((j+1-i+k) % k == 0) if(str[j-1] == '0') dp[i][j]++;
if((j+1-i+k) % k != 0) if(str[j-1] == '1') dp[i][j]++;
}
}
int l , r;
while(w--)
{
scanf("%d%d", &l ,&r);
int t = l % k;
int cnt = 0;
cnt = dp[t][r] - dp[t][l] + sol(l);
printf("%d\n", cnt);
}
return 0;
}