思路
把n*n的矩阵摊平成一条直线,就可以用线段树的方法解决啦!
n<1000,所以展成直线就是1e6的单点修改+区间求和。
个人码风问题我全开ll了,第一发因为update写错了爆零(我太菜了)
代码
#include<stdio.h>
#include<iostream>
#include<cstring>
#define int ll
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int tree[maxn*4],n,m,f,x1,x2,y1,y2;
bool num[maxn];
void build(int node,int start,int end){
if(start==end){
tree[node]=num[start];
return;
}
int mid=start+end>>1;
build(node<<1,start,mid);
build(node<<1|1,mid+1,end);
tree[node]=tree[node<<1]+tree[node<<1|1];
}
void update(int node,int start,int end,int id){
if(start==end){
tree[node]^=1;
num[id]^=1;
return;
}
int mid=(start+end)>>1;
if(id<=mid) update(node<<1,start,mid,id);
if(id>mid) update(node<<1|1,mid+1,end,id);
tree[node]=tree[node<<1]+tree[node<<1|1];
}
int query(int node,int start,int end,int l,int r){
if(l<=start&&end<=r) return tree[node];
int mid=(start+end)>>1;
int res=0;
if(l<=mid) res+=query(node<<1,start,mid,l,r);
if(r>mid) res+=query(node<<1|1,mid+1,end,l,r);
return res;
}
signed main(){
scanf("%lld%lld",&n,&m);
int N=n*n;
for(int i=0;i<n;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&num[i*n+j]);
build(1,1,N);
for(int i=1;i<=m;i++){
scanf("%lld",&f);
if(f==1){
scanf("%lld%lld",&x1,&y1);
update(1,1,N,(x1-1)*n+y1);
}else if(f==2){
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
if(x1>x2) swap(x1,x2);
if(y1>y2) swap(y1,y2);
int ans=0;
for(int j=x1;j<=x2;j++){
ans+=query(1,1,N,(j-1)*n+y1,(j-1)*n+y2);
}
printf("%lld\n",ans);
}
// for(int i=1;i<=4*N;i++) cout<<tree[i]<<" ";
}
return 0;
} 
京公网安备 11010502036488号