bzoj4941: [Ynoi2016]镜子里的昆虫

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4941: [Ynoi2016]镜子里的昆虫相关的知识,希望对你有一定的参考价值。

维护每个位置x的上一个相等的位置pv[x],可以把询问表示成l<=x<=r,pv[x]<l的形式,对一次修改,均摊改变O(1)个pv的取值,因此可以用平衡树预处理出pv的变化,用cdq分治处理查询。

#include<bits/stdc++.h>
char buf[3000007],*ptr=buf;
const int N=100007;
int _(){
    int x=0;
    while(*ptr<48)++ptr;
    while(*ptr>47)x=x*10+*ptr++-48;
    return x;
}
struct itv{
    int l;
    mutable int r,x;
    bool operator<(const itv&w)const{return l<w.l;}
};
typedef std::set<itv>::iterator IT;
std::set<itv>c,cs[N*2];
int n,m,v0[N],vs[N*2],vp=0;
int os[N][4],pw[N*2],pv[N];
struct P{
    int t,x,y,a;
    bool operator<(const P&w)const{return x<w.x;}
}ps[N*10],qs[N*2],pb[N*10];
int px[N],qx[N];
int pp=0,qp=0,now,ans[N];
int bit[N][2],tk=1,c0;
void inc(int w,int a){
    if(!w)c0+=a;
    else for(;w<=n;w+=w&-w){
        bit[w][0]!=tk?bit[w][0]=tk,bit[w][1]=0:0;
        bit[w][1]+=a;
    }
}
int sum(int w){
    int s=c0;
    for(;w;w-=w&-w){
        s+=(bit[w][0]==tk?bit[w][1]:0);
    }
    return s;
}
void clr(){
    ++tk,c0=0;
}
void msort(P*l,P*m,P*r){
    P*bp=pb,*p1=l,*p2=m;
    while(p1!=m&&p2!=r)*bp++=*(p1->x<p2->x?p1:p2)++;
    while(p1!=m)*bp++=*p1++;
    while(p2!=r)*bp++=*p2++;
    memcpy(l,pb,(r-l)*sizeof(P));
}
void calc(int L,int R,int lp,int rp,int lq,int rq){
    if(L==R){
        std::sort(ps+lp,ps+rp);
        std::sort(qs+lq,qs+rq);
        return;
    }
    int M=(L+R)>>1,mp=px[M],mq=qx[M];
    calc(L,M,lp,mp,lq,mq);
    calc(M+1,R,mp,rp,mq,rq);
    if(lp<mp&&mq<rq){
        clr();
        for(int i=mq,j=lp;i<rq;++i){
            for(;j<mp&&ps[j].x<=qs[i].x;++j)inc(ps[j].y,ps[j].a);
            int z;
            ans[qs[i].t]+=z=sum(qs[i].y)*qs[i].a;
        }
    }
    msort(ps+lp,ps+mp,ps+rp);
    msort(qs+lq,qs+mq,qs+rq);
}
void setpv(int w,int v){
    if(pv[w]==v)return;
    ps[pp++]=(P){now,w,pv[w],-1};
    pv[w]=v;
    ps[pp++]=(P){now,w,v,1};
}
int getpv(int w,int x){
    IT it=cs[w].lower_bound((itv){x});
    if(it==cs[w].begin())return 0;
    --it;
    return it->r>=x?x-1:it->r;
}
void setq(int l,int r){
    qs[qp++]=(P){now,r,l-1,1};
    qs[qp++]=(P){now,l-1,l-1,-1};
}
int xs[N],xp,cms[N],cp;
void modify(int l,int r,int x){
    IT it,it2,del;
    xp=cp=0;
    it=c.upper_bound((itv){r});--it;
    if(it->r>r){
        cs[it->x].insert((itv){r+1,it->r});
        cs[it->x].find(*it)->r=r;
        c.insert((itv){r+1,it->r,it->x});
        it->r=r;
    }
    it=c.upper_bound((itv){l});--it;
    if(it->l<l){
        cs[it->x].insert((itv){l,it->r});
        cs[it->x].find(*it)->r=l-1;
        c.insert((itv){l,it->r,it->x});
        it->r=l-1;
    }
    for(it=c.find((itv){l});it!=c.end();it2=it,++it,c.erase(it2)){
        xs[xp++]=it->l;
        if(it->l>r)break;
        cms[cp++]=it->x;
        cs[it->x].erase(*it);
    }
    c.insert((itv){l,r,x});
    cs[x].insert((itv){l,r});
    for(int i=0;i<xp;++i){
        int d=xs[i]-1;
        if(xs[i]==l)d=getpv(x,xs[i]);
        else if(xs[i]>r)d=getpv(it->x,xs[i]);
        setpv(xs[i],d);
    }
    cms[cp++]=x;
    for(int i=0;i<cp;++i){
        it=cs[cms[i]].upper_bound((itv){r});
        if(it!=cs[cms[i]].end()){
            setpv(it->l,getpv(cms[i],it->l));
        }
    }
}
int main(){
    fread(buf,1,sizeof(buf),stdin);
    n=_();m=_();
    for(int i=1;i<=n;++i)vs[vp++]=v0[i]=_();
    for(int i=1;i<=m;++i){
        os[i][0]=_();
        os[i][1]=_();
        os[i][2]=_();
        if(os[i][0]==1)vs[vp++]=os[i][3]=_();
    }
    std::sort(vs,vs+vp);
    vp=std::unique(vs,vs+vp)-vs;
    for(int i=1;i<=n;++i)v0[i]=std::lower_bound(vs,vs+vp,v0[i])-vs;
    for(int i=1;i<=m;++i)os[i][3]=std::lower_bound(vs,vs+vp,os[i][3])-vs;
    for(int i=1;i<=n;++i){
        cs[v0[i]].insert((itv){i,i});
        c.insert((itv){i,i,v0[i]});
        pv[i]=pw[v0[i]];
        ps[pp++]=(P){0,i,pv[i],1};
        pw[v0[i]]=i;
    }
    px[0]=pp,qx[0]=qp;
    for(int i=now=1;i<=m;++now,++i){
        if(os[i][0]==1)modify(os[i][1],os[i][2],os[i][3]);
        else setq(os[i][1],os[i][2]);
        px[i]=pp,qx[i]=qp;
    }
    calc(0,m,0,pp,0,qp);
    for(int i=1;i<=m;++i)if(os[i][0]==2)printf("%d\n",ans[i]);
    return 0;
}

 

以上是关于bzoj4941: [Ynoi2016]镜子里的昆虫的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4940: [Ynoi2016]这是我自己的发明

[bzoj 4939][Ynoi 2016]掉进兔子洞

BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)

bzoj 4939: [Ynoi2016]掉进兔子洞

bzoj4811[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并

BZOJ4810: [Ynoi2017]由乃的玉米田