珂朵莉树吼啊!!!
对于操作$0$,其实就是区间赋值为$0$的操作,直接套模板就行了
对于操作$1$,应该是这个题目最难的操作了(虽然还是很简单),我们先查询$(l_0,r_0)$这个区间的$1$的数量,最后扫一遍$(l_1,r_1)$这个区间,如果$1$的数量够的话直接更改区间值,如果不够的话就把其中够的那块区间赋值就行了,详细看代码
对于操作$2$,直接模板查询就行了
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#define Set set<Node>::iterator
#define N 200007
using namespace std;
struct Node
{
int l,r;
mutable int val;
Node(int L,int R,int V):l(L),r(R),val(V){}
Node(int L):l(L){}
bool operator<(const Node &it)const
{
return l<it.l;
}
};
set<Node> st;
int n,m;
Set Split(int x)
{
Set it=st.lower_bound(Node(x));
if(it!=st.end()&&it->l==x)
return it;
--it;
int L=it->l,R=it->r,V=it->val;
st.erase(it);
st.insert(Node(L,x-1,V));
return st.insert(Node(x,R,V)).first;
}
void Change(int l,int r,int v)
{
Set rr=Split(r+1),ll=Split(l);
st.erase(ll,rr);
st.insert(Node(l,r,v));
}
void Hos(int l1,int r1,int l2,int r2)
{
Set rr=Split(r1+1),ll=Split(l1);
int cnt=0;
for(Set it=ll;it!=rr;++it)
if(it->val)
cnt+=it->r-it->l+1;
Change(l1,r1,0);
rr=Split(r2+1),ll=Split(l2);
for(Set it=ll;it!=rr;++it)
{
if(!cnt)
break;
if(!it->val)
{
if(cnt>=it->r-it->l+1)
it->val=1,cnt-=it->r-it->l+1;
else
Change(it->l,it->l+cnt-1,1),cnt=0;
}
}
}
int Search(int l,int r)
{
int ans=0,maxn=0;
Set rr=Split(r+1),ll=Split(l);
for(Set it=ll;it!=rr;++it)
if(it->val)
ans=max(ans,maxn),maxn=0;
else
maxn+=it->r-it->l+1;
ans=max(ans,maxn);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
st.insert(Node(1,n,1));
st.insert(Node(n+1));
for(int i=1;i<=m;++i)
{
int opt,l,r,ll,rr;
scanf("%d%d%d",&opt,&l,&r);
if(!opt)
Change(l,r,0);
if(opt==1)
{
scanf("%d%d",&ll,&rr);
Hos(l,r,ll,rr);
}
if(opt==2)
printf("%d
",Search(l,r));
}
return 0;
}