链接
http://acm.hdu.edu.cn/showproblem.php?pid=3670
题解
这题不太好做
我首先是写了写看到一些规律
比如当查询
Q
1
Q\ 1
Q 1的时候,可以发现,当总的修改值为奇数的时候查询结果是奇数的个数,当总的修改值为偶数的时候查询的结果是偶数的个数,那么这个就很好做
然后考虑
Q
2
Q\ 2
Q 2有没有类似的规律,这个要稍微画一画图,然后就确实发现一些规律,按照总修改值对
4
4
4取模的值,查询的结果分为四种情况。然后我考虑算贡献,每种数字对
Q
2
Q\ 2
Q 2的影响和
d
d
d有关(这里
d
d
d就是总修改值对
4
4
4取模的结果),而且会发现这种贡献是连续的,比如数字
1
1
1对
Q
2
Q\ 2
Q 2的贡献就是:当
d
=
1
d=1
d=1或
d
=
2
d=2
d=2时,
Q
2
Q\ 2
Q 2的查询结果才会包含
c
n
t
1
cnt_1
cnt1(这里
c
n
t
1
cnt_1
cnt1)表示原序列中
1
1
1的个数
代码
#include <bits/stdc++.h>
#define maxn (65536+10)
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int cnt[maxn], N, f[20][maxn];
int read(int x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void init()
{
int i, j, mask, l, pos;
cl(cnt), cl(f);
for(i=1;i<=N;i++)cnt[read()]++;
for(i=0;i<65536;i++)
{
for(j=0;j<16;j++)
{
mask=(1<<j+1)-1;
if( (i&mask) > (1<<j) )
{
f[j][0] += cnt[i];
f[j][mask-(i&mask)+1]-=cnt[i];
f[j][mask-(i&mask)+(1<<j)+1]+=cnt[i];
}
else
{
f[j][(1<<j)-(i&mask)]+=cnt[i];
f[j][(1<<j)-(i&mask)+(1<<j)]-=cnt[i];
}
}
}
for(j=0;j<16;j++)for(i=1;i<(1<<j+1);i++)f[j][i]+=f[j][i-1];
}
int main()
{
char s[10];
int d, kase(0);
long long ans;
while( (N=read()) != -1 )
{
init();
d=0;
ans=0;
while(1)
{
scanf("%s",s);
if(s[0]=='Q')
{
auto x=read();
ans += f[x][d&((1<<x+1)-1)];
}
else if(s[0]=='C')
{
auto x=read();
d += x&65535;
d &= 65535;
}
else break;
}
printf("Case %d: %lld\n",++kase,ans);
}
return 0;
}