题目本质是求非同色正方形且边长为2的幂的个数。
这个2的幂条件简直给线段树量身定做。
cnt(i)即边长为2^i的同色正方形个数。纯色总数减去同色个数*4(因为有4的贡献被去掉了)就是异色贡献。
最多一百万行列,我们分边长来考虑。
对于边长为2^i的正方形,很明显其由一条长为2^i的横边和一条长为2^i的纵边围成,任何两条这样的边可以成为一个这样的正方形。
所以我们分横纵分别维护。
我们令黑,白权值分别为0,1
对于一个区间,我们维护这个区间颜色和。很明显,只有当和为0或者r-l+1时,才意味着这个区间颜色相同。
那每次分黑白讨论pushup即可。巧妙预处理lg很方便计算。
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define mid (l+r>>1)
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
int lg[1400003];
struct node{
int cnt[23];
struct bili{
int l,r,sum;
}t[4000003];
void pushup(int u,int l,int r){
int pre=t[u].sum;
t[u].sum=t[u*2].sum+t[u*2+1].sum;
if(pre==1&&t[u].sum==0||pre==r-l&&t[u].sum==r-l+1)cnt[lg[r-l+1]]++;
if(pre==0&&t[u].sum==1||pre==r-l+1&&t[u].sum==r-l)cnt[lg[r-l+1]]--;
}
void build(int u,int l,int r){
t[u].l=l;t[u].r=r;//t[u].sum++;
cnt[lg[r-l+1]]++;
if(l==r)return;build(u*2,l,mid);build(u*2+1,mid+1,r);
pushup(u,l,r);
}
void modify(int u,int l,int r,int pos){
if(t[u].l>pos||t[u].r<pos)return;
if(pos==t[u].l&&t[u].l==t[u].r){
t[u].sum^=1;return;
}modify(u*2,l,mid,pos);modify(u*2+1,mid+1,r,pos);
pushup(u,l,r);
}
}t[2];int n,q,s;
int ksm(int a,int b){
int sum=1;
while(b){
if(b&1)sum=sum*a;a=a*a;b>>=1;
}return sum;
}
signed main(){
for(int i=2;i<=1400000;i++)lg[i]=lg[i>>1]+1;
n=in;q=in;s=(1<<n);t[0].build(1,1,s);t[1].build(1,1,s);
while(q--){
int op=in;int x=in;
t[op].modify(1,1,s,x);
int ans=0;
for(int i=0;i<=n;i++){
ans=(ans+ksm(2,2*n-2*i));
if(i)ans=(ans-4*t[0].cnt[i]*t[1].cnt[i]);
}cout<<ans<<'\n';
}
return 0;
}