题目描述
分块
2*3的矩形可以压成64以内的二进制数。
我们分块,对于每块,维护块内每个前缀异或的桶,以及整个块异或值,因为有区间修改还要有修改tag,然后便容易询问与修改。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=1000000+10,maxd=64;
int cnt[maxn/100+10][maxd+10],num[maxn/100+10],tag[maxn/100+10],belong[maxn],ac[20];
int id[20][20];
int a[maxn];
bool bz[maxn/100+10];
int i,j,k,l,t,n,m,r,q,wdc,B;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void mark(int x,int v){
bz[x]=1;
tag[x]=v;
}
void down(int x){
if (!bz[x]) return;
int i;
fo(i,(x-1)*B+1,min(B*x,n)) a[i]=ac[tag[x]];
bz[x]=0;
}
void rebuild(int x){
down(x);
int i,t=0;
fo(i,0,maxd-1) cnt[x][i]=0;
fo(i,(x-1)*B+1,min(B*x,n)){
t^=a[i];
cnt[x][t]++;
}
num[x]=t;
}
int query(int j,int k){
int i,t=0,ans=0,x;
int l=belong[j],r=belong[k];
if (l==r){
fo(i,1,l-1){
if (bz[i]){
if (B%2) t^=ac[tag[i]];
}
else t^=num[i];
}
fo(i,(l-1)*B+1,min(l*B,n)){
if (bz[l]) t^=ac[tag[l]];else t^=a[i];
if (j<=i&&i<=k&&t==wdc) ans++;
}
return ans;
}
fo(i,1,l-1){
if (bz[i]){
if (B%2) t^=ac[tag[i]];
}
else t^=num[i];
}
fo(i,(l-1)*B+1,l*B){
if (bz[l]) t^=ac[tag[l]];else t^=a[i];
if (j<=i&&t==wdc) ans++;
}
fo(i,l+1,r-1){
if (bz[i]){
if ((ac[tag[i]]^t)==wdc) ans+=(B+1)/2;
if (t==wdc) ans+=B/2;
if (B%2) t^=ac[tag[i]];
}
else{
ans+=cnt[i][wdc^t];
t^=num[i];
}
}
fo(i,(r-1)*B+1,k){
if (bz[r]) t^=ac[tag[r]];else t^=a[i];
if (t==wdc) ans++;
}
return ans;
}
void change(int j,int k,int v){
int i;
int l=belong[j],r=belong[k];
if (l==r){
down(l);
fo(i,j,k) a[i]=ac[v];
rebuild(l);
return;
}
fo(i,l+1,r-1) mark(i,v);
down(l);
fo(i,j,l*B) a[i]=ac[v];
rebuild(l);
down(r);
fo(i,(r-1)*B+1,k) a[i]=ac[v];
rebuild(r);
}
int main(){
freopen("ji.in","r",stdin);freopen("ji.out","w",stdout);
n=read();m=read();
wdc=0;
fo(i,1,n)
fo(j,1,m){
t=read();
wdc=wdc*2+t;
}
t=0;
fd(i,n,1)
fd(j,m,1)
id[i][j]=t++;
fo(i,1,n){
ac[i]=0;
fo(j,1,m) ac[i]+=(1<<id[i][j]);
}
fo(j,1,m){
ac[j+n]=0;
fo(i,1,n) ac[j+n]+=(1<<id[i][j]);
}
n=read();m=read();
//B=floor(sqrt(n));
//B=1;
B=600;
fo(i,1,n) belong[i]=(i-1)/B+1;
fo(i,1,belong[n]){
mark(i,1);
rebuild(i);
}
while (m--){
t=read();
if (t==0){
j=read();k=read();
down(belong[j]);
a[j]=ac[k];
rebuild(belong[j]);
}
else if (t==1){
j=read();k=read();
printf("%d\n",query(j,k));
}
else{
j=read();k=read();l=read();
change(j,k,l);
}
}
}