周末UA做了这场多校的vjudge版本。
我去陪爸妈去山沟沟转了,回来听说有个这个线段树,想敲敲。
多年不做线段树,好恶心><
struct Tnode{ // 一维线段树
int l,r;
int cover;
int lid, rid;
int sum;
int len() { return r - l;}
int mid() { return MID(l,r);}
bool in(int ll,int rr) { return l >= ll && r <= rr; }
void lr(int ll,int rr){ l = ll; r = rr;}
};
这个是我每次都用的线段树定义,根据题目不同,会更改一些标记。
根据这个题来说,cover = 0表示该区间的位置都为空,cover=1表示该区间都不为空,cover=-1表示部分为空(借鉴于zoj线段覆盖那道题)
sum表示该区间里为空的位置长度和。
lid表示该区间最左边为空的位置号,rid为最右边为空的位置号。若sum = 0,则lid rid都为-1。
操作1:
输入a ,b
比较麻烦,求左端点很简单,直接查询下就行了。求出左端点lpos。若为-1输出Can not balabala。。
求右端点的时候我是先求出0~lpos中间的空位置val,然后求从0~n-1中空位置大于等于val+b的位置。方便分。
因为纠结一点,不知道如何在区间[l,r]中查找空位置为d的位置(就我目前维护的标记来说),但是查找[0,r]的位置会很easy~懂吧?
操作2:
求个sum即可
出错地方:查左端点的时候,如果左边查不到,那么右边得查,我直接左边差不到就返回了。要知道如果[l,r]区间中有sum>0的位置,但是空位置不一定是在需要的区间中。
比如区间[0, 9]中有空位置[0,1]和[5,6],但是呢,我需要的是[3, 6]中的空位置,显然mid后,左边[0,5]有空位置,但是是找不到对应的在[3,6]的空位置的。改过就过了。
时间:C++,400+MS,估计是用指针了,慢了,但是真心不习惯用数组替代,唉唉唉。
#include
#include