cf C. Inna and Candy Boxes

题意:给你一个长度为n的只含有1和0的字符串,w个询问,每次询问输入l,r;在[l,r]中在l+k-1、l+2*k-1、......r的位置都必须为1,如果不为1的,变成1,记为一次操作,其它的地方的都必须为0,不为0的地方要变成1,也记为一次操作,最后问在区间[l,r]最少几次操作。

思路:可以用树状数组记录在某个地方的右方有多少个1,然后在 预处理出从1,2,..k的为开头的在i+c*k-1的位置上前面有多少个1,最后的答案是拿走的1+添加的1,拿走的1的个数等于现有的1的个数-位置正确的1的个数。 添加的1的个数等于需要添加的个数的总数-位置正确的1的个数。

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #define maxn 100010

 5 using namespace std;

 6 

 7 int n,k,w;

 8 char str[maxn];

 9 int a[maxn];

10 int c[maxn];

11 int dp[maxn];

12 int sum[maxn];

13 

14 int lowbit(int x)

15 {

16     return x&-x;

17 }

18 

19 void insert(int x,int d)

20 {

21     while(x<maxn)

22     {

23        c[x]+=d;

24        x+=lowbit(x);

25     }

26 }

27 

28 int Getsum(int x)

29 {

30     int ans=0;

31     while(x>0)

32     {

33         ans+=c[x];

34         x-=lowbit(x);

35     }

36     return ans;

37 }

38 

39 

40 int main()

41 {

42     while(scanf("%d%d%d",&n,&k,&w)!=EOF)

43     {

44          scanf("%s",str+1);

45          memset(sum,0,sizeof(sum));

46          memset(a,0,sizeof(a));

47          memset(c,0,sizeof(c));

48          for(int i=1; i<=n; i++)

49          {

50             if(str[i]=='1')

51             {

52                 insert(i,1);

53             }

54          }

55          for(int i=1; i<=k; i++)

56          {

57              int cnt=0;

58              for(int c=1; i+c*k-1<=n; c++)

59              {

60                   cnt+=(str[i+c*k-1]-'0');

61                   dp[i+c*k-1]=cnt;

62              }

63          }

64          for(int i=1; i<=w; i++)

65          {

66              int l,r;

67              int ans=0;

68              scanf("%d%d",&l,&r);

69              int num=(r-l+1)/k;

70              ans+=Getsum(r)-Getsum(l-1);

71              ans-=dp[r]-dp[l-1];

72              ans+=num;

73              ans-=dp[r]-dp[l-1];

74              printf("%d\n",ans);

75          }

76     }

77     return 0;

78 }
View Code

 

你可能感兴趣的:(in)