这道题超级可爱呢,珂朵莉最可爱了,不,小哀才是最可爱的呢
很好的题,可以考虑用线段树维护,hale表示线段树思路很难,而且难打,不如滚去写珂朵莉树哦
对于操作一:直接将set修改插入即可
对于操作三:最大连续子段和(线段树里面是这样叫的吧)维护即可
对于操作二:我们发现可以考虑先将这段区间里面的1 全部取出来,然后暴力合并区间为0,插入会set里面
之后枚举要修改的区间,从左端点开始搞起,一直后搜索,最后加一个判断,是否已经完全ok即可,具体可参见代码
好了,这道题就解决了
我的代码好像luogu会RE四个点,莫名其妙,loj就可以直接AC了,开心
#include#define IT set ::iteratorusing namespace std;const int N=2e5+7;int m,n;struct node{ int l,r; mutable int v; node(int L,int R=-1,int V=0):l(L),r(R),v(V){} bool operator<(const node &x) const { return l s;IT split(int pos){ IT it=s.lower_bound(node(pos)); if (it!=s.end()&&it->l==pos) return it; it--; int L=it->l,R=it->r,V=it->v; s.erase(it); s.insert(node(L,pos-1,V)); return s.insert(node(pos,R,V)).first;}void del(int l,int r){ IT itr=split(r+1),itl=split(l); s.erase(itl,itr); s.insert(node(l,r,0));}int query(int l,int r){ int ans=0,mx=0; IT itr=split(r+1),itl=split(l); for (;itl!=itr;itl++) if (!itl->v) ans+=itl->r-itl->l+1; else mx=max(mx,ans),ans=0; return max(mx,ans);}void put(int l0,int r0,int l,int r){ IT itr=split(r0+1),itl=split(l0),it=itl; int sum=0; for (;itl!=itr;itl++) if (itl->v) sum+=itl->r-itl->l+1; s.erase(it,itr);s.insert(node(l0,r0,0)); itr=split(r+1);it=itl=split(l); int tot=0; for (;itl!=itr&&tot v) tot+=itl->r-itl->l+1; if (itl==itr&&tot<=sum) s.erase(it,itr),s.insert(node(l,r,1)); else { int pos=itl->l+sum-tot-1; IT itp=split(pos+1); s.erase(it,itp); s.insert(node(l,pos,1)); }}int main(){ scanf("%d%d",&n,&m); s.insert(node(1,n,1));s.insert(node(n+1,n+1,0)); for (int i=1;i<=m;i++) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if (op==0) del(l,r); if (op==2) printf("%d\n",query(l,r)); if (op==1) { int l0,r0;scanf("%d%d",&l0,&r0); put(l,r,l0,r0); } } return 0;}