P3801 红色的幻想乡

P3801 红色的幻想乡


题意

给定 m 次操作:

  • 给出 (x,y) 将第 x 行第 y 列反转(将0变成1,将1变成0)。
  • 给出 (x1,y1) 和 (x2,y2) ,表示查询两点围成的矩阵中有多少个1。

分析

树状数组/线段树。

直接分别维护行列的0/1情况,分别计算行与列的贡献再减去相交处重复计算的贡献即可。

Codes:

#include<bits/stdc++.h>
using namespace std;

const int N=5e5+100,M=5e5;
typedef long long ll;
int n,m,q,lim;
int g[N],h[2][N],b[2]={1,-1};
struct operation
{
    int dx[2],dy[2],opt;
}f[N];

struct indextree
{
    int c[2][N];
    int lowbit(int x){return x&(-x);}
    void upd(int x,int opt,int z)
    {
        if(x<1)return ;
        while(x<=lim)
        {
            c[opt][x]+=z;
            x+=lowbit(x);
        }
    }

    int que(int x,int opt)
    {
        if(x<1)return 0;
        int sum=0;
        while(x)
        {
            sum+=c[opt][x];
            x-=lowbit(x);
        }
        return sum;
    }
}T;
void init()
{
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1,opt,x,y;i<=q;++i)
    {
        scanf("%d%d%d",&opt,&x,&y);
        f[i].opt=opt;
        f[i].dx[0]=x;
        f[i].dy[0]=y;
        g[++g[0]]=x;
        g[++g[0]]=y;
        if(opt==2)
        {
            scanf("%d%d",&x,&y);
            f[i].dx[1]=x;
            f[i].dy[1]=y;
            g[++g[0]]=x;
            g[++g[0]]=y;
        }
    }

}

int got(int x)
{
    return lower_bound(g+1,g+1+lim,x)-g;
}

void loading()
{
    sort(g+1,g+1+g[0]);
    lim=unique(g+1,g+1+g[0])-g-1;
}

void work()
{
    for(int i=1,x,y;i<=q;++i)
    {
        if(f[i].opt==1)
        {
            x=got(f[i].dx[0]);
            y=got(f[i].dy[0]);
            T.upd(x,0,b[h[0][x]]);
            T.upd(y,1,b[h[1][y]]);
            h[0][x]^=1;
            h[1][y]^=1;
        }
        else
        {
            ll sum1=0,sum2=0;
            ll len1=f[i].dx[1]-f[i].dx[0]+1;
            ll len2=f[i].dy[1]-f[i].dy[0]+1;
            x=got(f[i].dx[0]);
            y=got(f[i].dx[1]);
            sum1=T.que(y,0)-T.que(x-1,0);
            x=got(f[i].dy[0]);
            y=got(f[i].dy[1]);
            sum2=T.que(y,1)-T.que(x-1,1);
            printf("%lld\n",sum1*len2+sum2*len1-2ll*sum1*sum2);
        }
    }
}

int main()
{
    init();
    loading();
    work();
    return 0;
}
posted @ 2025-01-31 17:15  Glowingfire  阅读(23)  评论(0)    收藏  举报