题意简析:你需要写一个数据结构,维护一个时间轴,支持如下操作:
1)插入1个新区间,删除所有时间轴上与它有交的区间并输出个数。
2)查询当前时间轴上的区间个数。
解题思路:裸的无旋treap即可。按照双端点排序,然后找前驱后继,进行操作即可。
AC代码:(目前是洛谷 Rank1 596ms)
#include <stdio.h>
#define r register
#define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
char BB[<<],*S=BB,*TT=BB;
inline int in(){
r int x=; r bool f=; r char c;
for (;(c=getchar())<''||c>'';f=c=='-');
for (x=c-'';(c=getchar())>=''&&c<='';x=(x<<)+(x<<)+c-'');
return f?-x:x;
}
namespace Treap{
inline int Rand(){
static int x=;
return x^=x<<,x^=x>>,x^=x<<;
}
struct task{int lt,rt;};
struct node{
node *ls,*rs;task v;int pri,sz;
node(task a):v(a){ls=rs=NULL;pri=Rand();sz=;}
inline void up(){sz=(ls?ls->sz:)+(rs?rs->sz:)+;}
}*root;
struct Droot{node *a,*b;};
inline int Size(node *x){return x?x->sz:;}
node *merge(node *a,node *b){
if (!a) return b;
if (!b) return a;
if (a->pri<b->pri){
a->rs=merge(a->rs,b);
a->up();return a;
}else{
b->ls=merge(a,b->ls);
b->up();return b;
}
}
Droot split(node *a,int k){
if (!a) return (Droot){NULL,NULL};
r Droot y;if (Size(a->ls)>=k){
y=split(a->ls,k);
a->ls=y.b;a->up();y.b=a;
}else{
y=split(a->rs,k-Size(a->ls)-);
a->rs=y.a;a->up();y.a=a;
}return y;
}
int find_pre(node *x,task a){
if (!x) return ;
if (x->v.rt<a.lt) return find_pre(x->rs,a)+Size(x->ls)+;
return find_pre(x->ls,a);
}
int find_nxt(node *x,task a){
if (!x) return ;
if (x->v.lt>a.rt) return find_nxt(x->ls,a);
return find_nxt(x->rs,a)+Size(x->ls)+;
}
inline int new_task(){
r task a;a.lt=in(),a.rt=in();
r int L=find_pre(root,a),R=find_nxt(root,a);
r Droot y=split(root,R);r Droot x=split(y.a,L);
r int ans=Size(x.b);r node *newd=new node(a);
root=merge(merge(x.a,newd),y.b);return ans;
}
inline int Get_Ans(){return Size(root);}
}
int main(){
int q=in();while(q--){
char op=getchar(); while(op!='A'&&op!='B') op=getchar();
if (op=='A') printf("%d\n",Treap::new_task());
else printf("%d\n",Treap::Get_Ans());
}
}