Codeforces Round #654 (Div. 2) F.Raging Thunder(线段树区间合并)

    技术2024-12-11  16

    题目

    一个长为n(n<=5e5)的仅由'>"和'<'构成的字符串,

    代表球桌上在1到n的位置,有n个转换器,

    此外,球桌上还有0到n,共n+1个球洞,假设此时球碰到i位置的转换器,

    对于i位置的<转换器,

    ①如果i=1,球会落到0位置球洞

    ②如果i-1位置是<转换器,球会滚到i-1的转换器

    ③如果i-1位置是>转换器,球会落到i-1位置球洞

    对于i位置的>转换器,

    ①如果i=n,球会落到n位置球洞

    ②如果i+1位置是>转换器,球会滚到i+1的转换器

    ③如果i+1位置是<转换器,球会落到i位置球洞

    以下q(q<=1e5)组询问,每次给出两个下标l,r,

    首先,对[l,r]这段区间的符号取反(大于号变小于号,小于号变大于号),取反操作保留到下一轮,

    然后在[l,r]每个转换器上都放一个小球,要求输出,含最多小球的球洞中,小球的个数

    本轮小球下落后即消失,不保留到下一轮

    思路来源

    Codeforces账户lucifer1004

    https://codeforces.com/contest/1371/submission/85729867

    题解

    多种做法,但别的没太看懂,只好多打点标记,于是变成区间合并码农题,

    如果出现><这样的情形,球会落在大于号的球洞里,

    只考虑[l,r]时,如果区间左侧是<<或右侧>>,

    说明会落在区间外的一个球洞里,因此答案是这三者的最大值

     

    考虑维护分区间前缀、后缀、最大值来维护,

    分别维护连续小于号、连续大于号、先一段小于号再一段大于号、先一段大于号再一段小于号

    即,pl:前缀<<,pr:前缀>>,plr:前缀<<>>,prl:前缀>><<,

    sl:后缀<<,sr:后缀>>,slr:后缀<<>>,srl:后缀>><<,

    mxlr:区间最大<<>>,mxrl:区间最大>><<

     

    考虑取反修改,完整区间就打取反标记,pushdown就将标记下放,pushup就将左子树和右子树merge

     

    考虑回答,回答时,全在左就回答左,全在右就回答右,否则回答左右询问的merge

     

    考虑pushup合并,pl、pr、sl、sr的合并是区间合并经典例题,区间最长01段的合并方法

     

    pl:前缀<<,先等于左的前缀<<,如果等于左区间长,再加上右的前缀<<①

     

    plr:前缀<>,先等于左的前缀<>,如果等于左区间长,再加上右的前缀>>①

    另一种情况是,左的前缀<<等于左区间长,

    若右的前缀>>非空,加上右的前缀>>②

    若右的前缀<<>>非空,加上右的前缀<<>>③

    注意到①、②、③三种情况互斥,故需要分别独立判断if

     

    mxrl:最大区间><,用左mxrl、右mxrl,当前前缀prl,当前后缀srl分别更新一下,

    然后考虑中间的两段,

    若左子后缀>>非空且右子前缀<<非空,拼成>><<

    无论左子后缀>>如何,若右子前缀>><<非空,拼成>><<

    若左子后缀>><<非空,无论右子前缀<<如何,拼成>><<

     

    以上若干情况,均可以考虑成,cin把cout向右推的一个过程,

    此时,把>>和<<的临界点分为在左边、中间、右边三种情况考虑

    代码

    #include<bits/stdc++.h> using namespace std; const int N=5e5+10; int n,q,l,r; char s[N]; struct node{ //p:前缀 s:后缀 l:小于号(朝左) r:大于号(朝右) mx:这一段最大值 int l,r,pl,pr,plr,prl,sl,sr,slr,srl,mxlr,mxrl; bool tag; void init(){ pl=pr=plr=prl=sl=sr=slr=srl=mxlr=mxrl=tag=0; } void out(){ printf("l:%d r:%d pl:%d pr:%d plr:%d prl:%d sl:%d sr:%d slr:%d srl:%d mxlr:%d mxrl:%d\n",l,r,pl,pr,plr,prl,sl,sr,slr,srl,mxlr,mxrl); } node(){ init(); } }e[5*N]; node merge(node a,node b){ node c; c.l=a.l;c.r=b.r; c.pl=a.pl;if(a.pl==a.r-a.l+1)c.pl+=b.pl;//一种情况 c.pr=a.pr;if(a.pr==a.r-a.l+1)c.pr+=b.pr; c.sl=b.sl;if(b.sl==b.r-b.l+1)c.sl+=a.sl; c.sr=b.sr;if(b.sr==b.r-b.l+1)c.sr+=a.sr; c.plr=a.plr;if(a.plr==a.r-a.l+1)c.plr+=b.pr;//三种情况 if(a.pl==a.r-a.l+1){ if(b.pr>0)c.plr=a.pl+b.pr; if(b.plr>0)c.plr=a.pl+b.plr; } c.prl=a.prl;if(a.prl==a.r-a.l+1)c.prl+=b.pl; if(a.pr==a.r-a.l+1){ if(b.pl>0)c.prl=a.pr+b.pl; if(b.prl>0)c.prl=a.pr+b.prl; } c.slr=b.slr;if(b.slr==b.r-b.l+1)c.slr+=a.sl; if(b.sr==b.r-b.l+1){ if(a.sl>0)c.slr=a.sl+b.sr; if(a.slr>0)c.slr=a.slr+b.sr; } c.srl=b.srl;if(b.srl==b.r-b.l+1)c.srl+=a.sr; if(b.sl==b.r-b.l+1){ if(a.sr>0)c.srl=a.sr+b.sl; if(a.srl>0)c.srl=a.srl+b.sl; } c.mxlr=max(c.plr,c.slr);//七种情况 if(a.sl>0 && b.pr>0)c.mxlr=max(c.mxlr,a.sl+b.pr); if(b.plr>0)c.mxlr=max(c.mxlr,a.sl+b.plr); if(a.slr>0)c.mxlr=max(c.mxlr,a.slr+b.pr); c.mxlr=max(c.mxlr,max(a.mxlr,b.mxlr)); c.mxrl=max(c.prl,c.srl); if(a.sr>0 && b.pl>0)c.mxrl=max(c.mxrl,a.sr+b.pl); if(b.prl>0)c.mxrl=max(c.mxrl,a.sr+b.prl); if(a.srl>0)c.mxrl=max(c.mxrl,a.srl+b.pl); c.mxrl=max(c.mxrl,max(a.mxrl,b.mxrl)); return c; } void bld(int p,int l,int r){ e[p].init(); e[p].l=l,e[p].r=r; if(l==r){ if(s[l]=='<')e[p].pl=e[p].sl=1; else e[p].pr=e[p].sr=1; return; } int mid=(l+r)/2; bld(p<<1,l,mid);bld(p<<1|1,mid+1,r); e[p]=merge(e[p<<1],e[p<<1|1]); } void flip(int p){ swap(e[p].pl,e[p].pr),swap(e[p].sl,e[p].sr); swap(e[p].plr,e[p].prl),swap(e[p].slr,e[p].srl),swap(e[p].mxlr,e[p].mxrl); e[p].tag^=1; } void psd(int p){ if(e[p].tag){ flip(p<<1),flip(p<<1|1); e[p].tag=0; } } node ask(int p,int ql,int qr){//区间翻转+询问 if(e[p].l==ql&&e[p].r==qr){ flip(p); return e[p]; } psd(p); int mid=(e[p].l+e[p].r)/2; node ans; if(qr<=mid)ans=ask(p<<1,ql,qr); else if(ql>mid)ans=ask(p<<1|1,ql,qr); else ans=merge(ask(p<<1,ql,mid),ask(p<<1|1,mid+1,qr)); e[p]=merge(e[p<<1],e[p<<1|1]); return ans; } int main(){ scanf("%d%d",&n,&q); scanf("%s",s+1); bld(1,1,n); while(q--){ scanf("%d%d",&l,&r); node ans=ask(1,l,r); printf("%d\n",max(ans.mxrl,max(ans.pl,ans.sr))); } return 0; }

     

    Processed: 0.095, SQL: 9