Problem Description
ivankevin loves sequences.
A sequence Gn of 2^n elements Gi is called a N-BIT REFLECTED GRAY SEQUENCE if:
1.Each element gi,j(0<=j<n) of Gi is a string contains n integers of 0 or 1.
2.G1=g1,0,g1,1=0,1.
3.if j<2^(n-1), then gn,j=0g(n-1),j,else gn,j=1g(n-1),2^n-1-j.
Now let a function f on gi,j be f(gi,j)=sum of all integers in gi,j. Given n, gn,a, and b, ivankevin wants to know the sum and the maximum of all f(gn,k mod 2^n) where a<=k<=a+b.
for example, let n=3, a=2, and b=3, then G3 is:
0 0 0,
0 0 1,
0 1 1,
0 1 0,
1 1 0,
1 1 1,
1 0 1,
1 0 0.
So f(g3,2)=2, f(g3,3)=1, then sum is 3 and the maximum is 2.
Input
The first line is an integer T, the number of test cases.
In each case, there are two integers n and b in the first line, as described. It is granted that 1<=n,b<=10000. The second line contains n integers of 0 or 1, indicating gn,a.
Output
For each test, print the sum and maximum to the relative query in a line, seqarated by a space.
Sample Input
1
3 1
0 0 1
Sample Output
ivankevin loves sequences.
A sequence Gn of 2^n elements Gi is called a N-BIT REFLECTED GRAY SEQUENCE if:
1.Each element gi,j(0<=j<n) of Gi is a string contains n integers of 0 or 1.
2.G1=g1,0,g1,1=0,1.
3.if j<2^(n-1), then gn,j=0g(n-1),j,else gn,j=1g(n-1),2^n-1-j.
Now let a function f on gi,j be f(gi,j)=sum of all integers in gi,j. Given n, gn,a, and b, ivankevin wants to know the sum and the maximum of all f(gn,k mod 2^n) where a<=k<=a+b.
for example, let n=3, a=2, and b=3, then G3 is:
0 0 0,
0 0 1,
0 1 1,
0 1 0,
1 1 0,
1 1 1,
1 0 1,
1 0 0.
So f(g3,2)=2, f(g3,3)=1, then sum is 3 and the maximum is 2.
Input
The first line is an integer T, the number of test cases.
In each case, there are two integers n and b in the first line, as described. It is granted that 1<=n,b<=10000. The second line contains n integers of 0 or 1, indicating gn,a.
Output
For each test, print the sum and maximum to the relative query in a line, seqarated by a space.
Sample Input
1
3 1
0 0 1
Sample Output
3 2
//此题用到了树状数组的查找和更新功能
#include<stdio.h>
#include<string.h>
#define Max 100010
int tree[Max];
int input[Max];
int n,b;
int lowbit(int x)
{
return x & (-x);
}
void modify(int x,int add)//一维
{
while(x<=n)
{
tree[x]+=add;
x+=lowbit(x);
}
}
int get_sum(int x)//求1到x之间的和
{
int ret=0;
while(x!=0)
{
ret+=tree[x];
x-=lowbit(x);
}
return ret;
}
int find()
{
if(get_sum(1)==1) return 1;//树状数组小标只能从1开始,所以没有get_sum(0)这一项
int low=2,high=n,mid;
while(low<=high)
{
mid=(low+high)/2;
if(get_sum(mid-1)==0&&get_sum(mid)==1)
return mid;
else if(get_sum(mid-1)>0)
high=mid-1;
else low=mid+1;
}
return 0;//没找到的话,返回0
}
int main()
{
//freopen("b.txt","r",stdin);
int i,t,sum,max_sum,pos,total;
scanf("%d",&t);
while(t--)
{
memset(tree,0,sizeof(tree));
scanf("%d %d",&n,&b);
for(i=1;i<=n;i++)
scanf("%d",&input[n-i+1]);
for(i=1;i<=n;i++)
modify(i,input[i]);
total=sum=max_sum=get_sum(n);
while(b--)
{
if(sum%2==0) pos=1;//偶数行变奇数行,把第一个元素改变
else
{
pos=find();
if(pos==n&&input[pos]==1)
{
sum=0;
input[pos]=0;
modify(n,-1);
continue;//跳过以下的操作
}
else pos+=1;//奇数行变偶数行,找到该序列中的第一个1,然后将其后数字改变
}
if(input[pos]==1)
{
sum--;
modify(pos,-1);
input[pos]=0;
}
else
{
sum++;
modify(pos,1);
input[pos]=1;
}
total+=sum;
if(sum>max_sum) max_sum=sum;
}
printf("%d %d\n",total,max_sum);
}
return 0;
}