原题链接
考察:线段树
思路:
和校门外的树(增强版)那道题差不多,我们不用管哪些瓶子有花,哪些没有.只要add,范围内从小到大 = 1.只要删除,sum[l,r] = 0.
Code
#include <iostream>
#include <cstring>
using namespace std;
const int N = 50011,INF = 0x3f3f3f3f;
struct Node{
int l,r,sum,tag;
}tr[N<<2];
int n,m,ans_l,ans_r,f;
void build(int u,int l,int r)
{
tr[u] = {l,r,0,0};
if(l==r) return;
int mid = l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void push_up(int u)
{
tr[u].sum = tr[u<<1].sum+tr[u<<1|1].sum;
}
int get(int u)
{
return tr[u].r-tr[u].l+1;
}
void push_down(int u)
{
if(tr[u].tag==1)
{
tr[u<<1].sum = get(u<<1);
tr[u<<1|1].sum = get(u<<1|1);
tr[u<<1].tag = tr[u<<1|1].tag = tr[u].tag;
tr[u].tag = 0;
}
if(tr[u].tag==-1)
{
tr[u<<1].sum = 0,tr[u<<1|1].sum = 0;
tr[u<<1].tag = tr[u<<1|1].tag = tr[u].tag;
tr[u].tag = 0;
}
}
int del(int u,int l,int r)
{
int res = 0;
if(tr[u].l>=l&&tr[u].r<=r)
{
res+=tr[u].sum;
tr[u].sum = 0;
tr[u].tag = -1;
return res;
}
push_down(u);
int mid = tr[u].l+tr[u].r>>1;
if(l<=mid) res+=del(u<<1,l,r);
if(mid<r) res+=del(u<<1|1,l,r);
push_up(u);
return res;
}
void add(int u,int l,int r)
{
if(!f) return;
if(tr[u].sum==get(u)) return;
if(tr[u].l==tr[u].r)
{
if(!tr[u].sum) ans_l = min(ans_l,tr[u].l),ans_r = max(ans_r,tr[u].r),f-=1;
tr[u].sum = 1;
return;
}
if(tr[u].l>=l&&tr[u].r<=r&&f>=get(u)&&!tr[u].sum)
{
tr[u].sum = get(u);
f-=get(u);
ans_l = min(ans_l,tr[u].l);
ans_r = max(ans_r,tr[u].r);
tr[u].tag = 1;
return;
}
push_down(u);
int mid = tr[u].l+tr[u].r>>1;
if(l<=mid) add(u<<1,l,r);
if(mid<r) add(u<<1|1,l,r);
push_up(u);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
l++,r++;
if(op==2) { printf("%d\n",del(1,l,r));continue; }
ans_l = INF,ans_r = -INF;
f = --r;
add(1,l,n);
if(f==r) puts("Can not put any one.") ;
else printf("%d %d\n",ans_l-1,ans_r-1);
}
printf("\n");
}
return 0;
}