您的位置:首页 > 其它

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

2014-02-13 01:32 363 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: