线段树
两个数n,m, n表示花瓶数量0~n-1,开始全为空。接下来有m组,每组有数k,a,b;当k=1时, 从a位置开始插花,b为花数量,当花瓶有花时,跳过当前,直到找到空花瓶再插入,输出插入第一支花的位置和最后一支花的位置,花可以没插完,当一支都没有插入则输出Can not put any one.;当k=2时,清空【a,b】的花瓶,并输出在被清空的花的数量。
线段树用1表示空位,0表示有花。
清空实质就是统计a,b之间有多少花,并把区间a,b强制置1。
插花要有点技巧,设置两个查询函数:查询l,r之间空位的数量,查询从第开头数p个空位到哪。
这样从a开始插b朵花:先查询a到末尾与多少空位x,若x==0输出没法插花;x小于b就把b换成x,实际插x朵;否则插b朵。然后查询开头到a有多少空位k,从开头数k+1个空位到哪,数k+b个空位到哪。这两个数就是实际插花的左右端点。在将这个区间全置0即可。
应该有线段树上二分的写法,可以直接查询从a往右数b个空瓶到哪,可是我不会写。
注意题目从0开始编号,注意转换与边界处理。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=50005;
const int oo=0x3f3f3f3f;
typedef long long LL;
struct Stree
{
int sum, lpos, rpos;
int set;
Stree() { sum=lpos=rpos=0;set=-1; }
Stree(int _a, int _b, int _c) { sum=_a, lpos=_b, rpos=_c; }
}stree[MAXN<<2];
void pushup(int rt)
{
stree[rt].sum=stree[rt<<1].sum+stree[rt<<1|1].sum;
stree[rt].lpos=(stree[rt<<1].lpos==-1 ? stree[rt<<1|1].lpos : stree[rt<<1].lpos);
stree[rt].rpos=(stree[rt<<1|1].rpos==-1 ? stree[rt<<1].rpos : stree[rt<<1|1].rpos);
}
void build(int l, int r, int rt)
{
stree[rt].lpos=stree[rt].rpos=stree[rt].set=-1;
stree[rt].sum=0;
if(l==r)
{
stree[rt].lpos=stree[rt].rpos=l;
stree[rt].sum=1;
return;
}
int mid=(l+r)>>1;
build(lson), build(rson);
pushup(rt);
}
void pushdown(int l, int r, int rt)
{
if(stree[rt].set!=-1)
{
int c=stree[rt].set;
stree[rt<<1].set=stree[rt<<1|1].set=c;stree[rt].set=-1;
int mid=(l+r)>>1;
if(c==0)
{
stree[rt<<1].lpos=stree[rt<<1].rpos=stree[rt<<1|1].lpos=stree[rt<<1|1].rpos=-1;
stree[rt<<1].sum=stree[rt<<1|1].sum=0;
}
else
{
stree[rt<<1].lpos=l;
stree[rt<<1].rpos=mid;
stree[rt<<1|1].lpos=mid+1;
stree[rt<<1|1].rpos=r;
stree[rt<<1].sum=mid-l+1;
stree[rt<<1|1].sum=r-mid;
}
}
}
int update(int L, int R, int col, int l, int r, int rt)
{
if(L<=l&&r<=R)
{
if(col==1)
{
int c=stree[rt].sum;
c=r-l+1-c;
stree[rt].sum=r-l+1;
stree[rt].set=1;
stree[rt].lpos=l, stree[rt].rpos=r;
return c;
}
else
{
int c=stree[rt].sum;
stree[rt].sum=0;
stree[rt].set=0;
stree[rt].lpos=-1, stree[rt].rpos=-1;
return c;
}
}
int mid=(l+r)>>1;
pushdown(l, r, rt);
int res=0;
if(midelse if(R<=mid) res=update(L, R, col, lson);
else res=update(L, R, col, lson)+update(L, R, col, rson);
pushup(rt);
return res;
}
int query(int L, int R, int l, int r, int rt)
{
if(L<=l&&r<=R) return stree[rt].sum;
pushdown(l, r, rt);
int mid=(l+r)>>1;
if(R<=mid) return query(L, R, lson);
else if(midreturn query(L, R, rson);
else return query(L, R, lson)+query(L, R, rson);
}
int query_pos(int p, int l, int r, int rt)
{
if(l==r) return l;
else if(stree[rt].sum==p) return stree[rt].rpos;
int mid=(l+r)>>1;
pushdown(l, r, rt);
if(stree[rt<<1].sum>=p)
return query_pos(p, lson);
else
return query_pos(p-stree[rt<<1].sum, rson);
}
int main()
{
int T;scanf("%d", &T);
while(T--)
{
int n, m;scanf("%d%d", &n, &m);
build(1, n, 1);
while(m--)
{
int a, b, c;scanf("%d%d%d", &a, &b, &c);
if(a==1)
{
b++;
int sum=query(b, n, 1, n, 1);
if(sum==0) puts("Can not put any one.");
else
{
int pre=(b==1?0:query(1, b-1, 1, n, 1));
c=min(c, sum);
int l=query_pos(pre+1, 1, n, 1);
int r=query_pos(pre+c, 1, n, 1);
update(l, r, 0, 1, n, 1);
printf("%d %d\n", l-1, r-1);
}
}
else
{
printf("%d\n", update(b+1, c+1, 1, 1, n, 1));
}
}
printf("\n");
}
//system("pause");
return 0;
}