分块写法感悟
分块写法感悟
听说有很多大神听完一个数据结构或算法的讲解就直接能自己模拟出这个算法。不需要模板。
TQL%%%学弟
然而我还得自己写写。 我太菜了。
以TJOI开关这道题为例。
分块的精髓在于整块\(O(1)\),小块暴力,那么显然需要记录每个数位于哪个块里。想要知道每个数在哪个块里就需要记录块的大小,通常是根号N。
所以
block=sqrt(n);
for(int i=1;i<=n;i++)
b[i]=(i-1)/block+1;//注意是i-1
然后修改,小块暴力。要判断x,y在不在一个块里。
也就是:
for(int i=x;i<=min(y,b[x]*block);i++)
{
ans[b[x]]-=a[i]^lazy[b[x]];
a[i]^=1;
ans[b[x]]+=a[i]^lazy[b[x]];
}
然后维护后面的小块,需要加一个判断条件
代码:
if(b[x]!=b[y])
{
for(int i=(b[y]-1)*block+1;i<=y;i++)
{
ans[b[y]]-=a[i]^lazy[b[y]];
a[i]^=1;
ans[b[y]]+=a[i]^lazy[b[y]];
}
}
最后就是维护大块了
for(int i=b[x]+1;i<=b[y]-1;i++)
{
lazy[i]^=1;
ans[i]=block-ans[i];
}