P2161 [SHOI2009]Booking 会场预约

xiaoxiao2021-02-28  60

https://www.luogu.org/problem/show?pid=2161

题意简析:你需要写一个数据结构,维护一个时间轴,支持如下操作:

1)插入1个新区间,删除所有时间轴上与它有交的区间并输出个数。

2)查询当前时间轴上的区间个数。

我们可以用线段树来做(借鉴了sxb大神的代码)。离线处理。用线段树存序号的最小值。 当我们倒着插入第i号区间之前,在线段树里取最小值,那么当前插入的这个区间会影响到序号为查询出的最小值的这个区间,用ans[i]表示插入第i个区间时,有几个矛盾的区间。

#include<iostream> #include<cstdio> #include<cstring> #define M 100010 #define N 200010 using namespace std; int n,ans[N],al[N],ar[N],Q[N]; int a[4*M],m[4*M]; void pushdown(int o) { m[o<<1]=min(m[o],m[o<<1]);a[o<<1]=min(a[o<<1],m[o<<1]); m[o<<1|1]=min(m[o],m[o<<1|1]);a[o<<1|1]=min(a[o<<1|1],m[o<<1|1]); } void change(int o,int l,int r,int ql,int qr,int k) { int mid=(l+r)>>1; if(ql<=l&&qr>=r) { m[o]=min(m[o],k); a[o]=m[o]; return ; } if(a[o]!=a[0]) pushdown(o); if(ql<=mid) change(o<<1,l,mid,ql,qr,k); if(qr>mid) change(o<<1|1,mid+1,r,ql,qr,k); a[o]=min(a[o<<1],a[o<<1|1]); } int query(int o,int l,int r,int ql,int qr) { int mid=(l+r)>>1; if(ql<=l&&qr>=r) return a[o]; if(a[o]!=a[0]) pushdown(o); int minn=a[0]; if(ql<=mid) minn=min(minn,query(o<<1,l,mid,ql,qr)); if(qr>mid) minn=min(minn,query(o<<1|1,mid+1,r,ql,qr)); return minn; } int main() { scanf("%d",&n); memset(a,127,sizeof(a));memset(m,127,sizeof(m)); for(int i=1;i<=n;i++) { char P; cin>>P; if(P=='A') { Q[i]=1; scanf("%d%d",&al[i],&ar[i]); } } for(int i=n;i>=1;i--) if(Q[i]) { int tmp=query(1,1,N-10,al[i],ar[i]); if(tmp!=a[0]) ans[tmp]++; change(1,1,N-10,al[i],ar[i],i); } int sum=0; for(int i=1;i<=n;i++) { if(Q[i]) sum=sum+1-ans[i],printf("%d\n",ans[i]); else printf("%d\n",sum); } return 0; }

还有就是set的做法。 当读入一个新的预约时,不断查找已经存在的预约中end值大等于新预约start值,并且最接近该start值的预约,找到一个删除一个,直到不能删除为止。因为不冲突的预约都是不相互覆盖的,所以它们的start值与end值必然是递增序列,所以一旦一个预约不能删除,后面的预约也不能删除。 注意set中的元素的定义和set排序的原则。 建议画图理解。

#include<iostream> #include<cstdio> #include<set> using namespace std; struct H{ int L,R; bool operator <(const H&a) const{ if(a.R==R) return L<a.L; return R<a.R; } }; set <H> s; int n; int main() { set<H>::iterator it; char P; scanf("%d",&n); for(int i=1;i<=n;i++) { cin>>P; if(P=='A') { int l,r,ans=0; scanf("%d%d",&l,&r); while(1) { it=s.lower_bound((H){0,l}); if(it!=s.end()&&it->L<=r) { ans++; s.erase(it); continue; } else{ s.insert((H){l,r}); break; } } printf("%d\n",ans); } else printf("%d\n",s.size()); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-36204.html

最新回复(0)