ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C20220806T3 如何愉快地与方格玩耍

2022-08-31 13:04:10  阅读:153  来源: 互联网

标签:const int C20220806T3 玩耍 方格 l1 l2 c11 change


给定 \(n\times n\) 的黑白方格,期初所有颜色均为白色,支持以下操作

  1. 翻转 \([l,r]\) 行/列的颜色
  2. 翻转质数/合数 行/列的颜色
  3. 求 \([l1,r1]\) 行、 \([l2,r2]\) 列围成的区域内的所有方格中黑色方格的数量。

\(n\leq 10^5,m\leq 2\times 10^5\) 。


首先需要明确的是,本题中行列并不互相干扰,因为1,2两种操作都只会单独对行或列造成干扰,而若求出 \([l1,r1]\) 之间的被翻转成黑色的行数 \(ans1\) , \([l2,r2]\) 之间被翻转的列数 \(ans2\) ,那么答案就是

\[ans1\times(r2-l2+1)+ans2\times(r1-l1+1)-2\times ans1\times ans2 \]

知道这一点,我们就可以用数据结构来分别维护行和列。那么现在棘手的问题是如何处理质数和合数。

首先,1是要特殊考虑的,所以可以直接维护2个变量来存储第一行和第一列,其次考虑用线段树来维护序列。

定义以下变量到每个线段树的节点: \(p,r\) 分别表示区间内的质数数量和合数数量, \(psum,rsum\) 分别表示区间内被涂黑的质数个数和合数个数。同时,在合并时只需要将对应量相加即可。然后谈修改,每次修改都是将原先白的变成黑的,所以

\[psum=p-psum,rsum=r-rsum \]

即可,在修改时记录2个懒标记,分别对应 \(p\) 和 \(r\) 。那么,修改操作就可以用4元组来表示 \((l,r,pp,rr)\) 表示在 \([l,r]\) 区间内翻转/不翻转 \(p,r\) 所以操作1就是 \((l,r,1,1)\) ,操作2就是 \((1,n,0/1,0/1)\) 。

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mp std::make_pair
#define pii std::pair<int,int>
#define chkmin(_A,_B) (_A=min(_A,_B))
#define chkmax(_A,_B) (_A=max(_A,_B))
using std::max;
using std::min;
//--------------------FastInOut--------------------//
class IO{
    public:
        inline char read(){
            static const int IN_LEN =1<<18|1;
            static char buf[IN_LEN],*s,*t;
            return (s==t)&&(t=(s=buf)+fread(buf, 1, IN_LEN, stdin)),(s==t)?-1:*s++;
        }
        template<typename _Tp>inline IO &operator >>(_Tp &x){
            static char c11, boo;
            for (c11=read(),boo=0;!isdigit(c11);c11=read()) {
                if (c11==-1)
                    return *this;
                boo|=(c11=='-');
            }
            for(x=0;isdigit(c11);c11=read())
                x=x*10+(c11^'0');
            if(boo)
                x=-x;
            return *this;
        }
        inline void push(const char &c) {
            putchar(c);
        }
        template<typename _Tp>inline IO &operator <<( _Tp x){
            if (x<0)
                x=-x,push('-');
            static _Tp sta[35];
            _Tp top=0;
            do{
                sta[top++]=x%10,x/=10;
            }while(x);
            while(top)
                push(sta[--top]+'0');
            return *this;
        }
        inline IO &operator <<(char lastChar){
            push(lastChar);
            return *this; 
        }
}FIO;
 
int n,m;
int P[100005];
struct info{
    int p,r;
    int psum,rsum;
    info(int x=0){
        if(x==0)
            p=r=psum=rsum=0;
        else if(P[x]==0)
            p=1,psum=rsum=r=0;
        else
            r=1,psum=rsum=p=0;
    }
    friend info operator +(const info &A,const info &B){
        info ret;
        ret.psum=A.psum+B.psum;
        ret.rsum=A.rsum+B.rsum;
        ret.p=A.p+B.p;
        ret.r=A.r+B.r;
        return ret;
    }
};
struct SegmentTree{
        struct node{
            int tagp,tagr;
            info I;
        }nd[400005];
        #define ls(p) (p<<1)
        #define rs(p) (p<<1|1)
        void pushup(const int &p){
            nd[p].I=nd[ls(p)].I+nd[rs(p)].I;
        }
        void addtag(const int &p,const int &pp,const int &rr){
            if(pp==1){
                nd[p].tagp^=1;
                nd[p].I.psum=nd[p].I.p-nd[p].I.psum;
            }
            if(rr==1){
                nd[p].tagr^=1;
                nd[p].I.rsum=nd[p].I.r-nd[p].I.rsum;
            }
        }
        void pushdown(const int &p){
            if(nd[p].tagr+nd[p].tagp!=0){
                addtag(ls(p),nd[p].tagp,nd[p].tagr);
                addtag(rs(p),nd[p].tagp,nd[p].tagr);
                nd[p].tagp=nd[p].tagr=0;
            }
        }
        void build(const int &l,const int &r,const int &p){
            if(l==r){
                nd[p].I=info(l);
                return;
            }
            int mid=(l+r)>>1;
            build(l,mid,ls(p));
            build(mid+1,r,rs(p));
            pushup(p);
        }
        void change(const int &l,const int &r,const int &ql,const int &qr,const int &p,const int &pp,const int &rr){
            if(ql<=l && r<=qr){
                addtag(p,pp,rr);
                return ;
            }
            pushdown(p);
            int mid=(l+r)>>1;
            if(ql<=mid)
                change(l,mid,ql,qr,ls(p),pp,rr);
            if(qr>mid)
                change(mid+1,r,ql,qr,rs(p),pp,rr);
            pushup(p);
        }
        info getsum(const int &l,const int &r,const int &ql,const int &qr,const int &p){
            if(ql<=l && r<=qr)
                return nd[p].I;
            pushdown(p);
            int mid=(l+r)>>1;
            info gl,gr;
            if(ql<=mid)
                gl=getsum(l,mid,ql,qr,ls(p));
            if(qr>mid)
                gr=getsum(mid+1,r,ql,qr,rs(p));
            return gl+gr;
        }
}R,C;
int R1,C1;
int main(){
    FIO>>n>>m;
    for(int i=2;i<=n;++i){
        if(P[i]==0){
            for(int j=2;i*j<=n;++j){
                P[i*j]=1;
            }
        }
    }
    R.build(2,n,1);
    C.build(2,n,1);
    while(m--){
        char c=FIO.read();
        while(c!='N' && c!='M' && c!='Q' && c!='P' && c!='R'){
            c=FIO.read();
        }
        if(c=='M'){
            int l,r;
            FIO>>l>>r;
            R.change(2,n,max(2,l),r,1,1,1);
            if(l==1)
                R1^=1;
        }
        if(c=='N'){
            int l,r;
            FIO>>l>>r;
            C.change(2,n,max(2,l),r,1,1,1);
            if(l==1)
                C1^=1;
        }
        if(c=='P'){
            int v;
            FIO>>v;
            if(v==0){
                R.change(2,n,2,n,1,1,0);
            }
            else{
                C.change(2,n,2,n,1,1,0);
            }
        }
        if(c=='R'){
            int v;
            FIO>>v;
            if(v==0){
                R.change(2,n,2,n,1,0,1);
            }
            else{
                C.change(2,n,2,n,1,0,1);
            }
        }
        if(c=='Q'){
            ll l1,l2,r1,r2;
            FIO>>l1>>r1>>l2>>r2;
            info g1=R.getsum(2,n,max(l1,2ll),r1,1);
            ll ans1=g1.psum+g1.rsum+((l1==1)?R1:0);
            info g2=C.getsum(2,n,max(l2,2ll),r2,1);
            ll ans2=g2.psum+g2.rsum+((l2==1)?C1:0);
            FIO<<ans1*(r2-l2+1)+ans2*(r1-l1+1)-2ll*ans1*ans2<<'\n';
        }
    }
    return 0;
}

标签:const,int,C20220806T3,玩耍,方格,l1,l2,c11,change
来源: https://www.cnblogs.com/zhouzizhe/p/16642693.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有