思路

把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;
}