【luogu2161】【SHOI2009】Booking会场预约
题意简析:你需要写一个数据结构,维护一个时间轴,支持如下操作:
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[1<<15],*S=BB,*TT=BB; inline int in(){ r int x=0; r bool f=0; r char c; for (;(c=getchar())<'0'||c>'9';f=c=='-'); for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } namespace Treap{ inline int Rand(){ static int x=23333; return x^=x<<13,x^=x>>17,x^=x<<5; } 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=1;} inline void up(){sz=(ls?ls->sz:0)+(rs?rs->sz:0)+1;} }*root; struct Droot{node *a,*b;}; inline int Size(node *x){return x?x->sz:0;} 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)-1); a->rs=y.a;a->up();y.a=a; }return y; } int find_pre(node *x,task a){ if (!x) return 0; if (x->v.rt<a.lt) return find_pre(x->rs,a)+Size(x->ls)+1; return find_pre(x->ls,a); } int find_nxt(node *x,task a){ if (!x) return 0; if (x->v.lt>a.rt) return find_nxt(x->ls,a); return find_nxt(x->rs,a)+Size(x->ls)+1; } 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()); } }