NOIP模拟赛天下神凡 动态开点线段树
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP模拟赛天下神凡 动态开点线段树相关的知识,希望对你有一定的参考价值。
这些圆一定是在同一水平面上的,由于他们没有相交,因此我们发现他们每个人与外界关系可以分为,1.存在并圈圈 2.存在圈圈并被割,因此我们把所有的圆都加1,把被割的在加1,就可以啦,因此我们开一个线段树,维护一段区间有没有被全部覆盖
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #define R register #define MAXN 300000 using namespace std; typedef unsigned long UI; struct O { UI x,r; }o[MAXN+10]; int n; int comp(const O a,const O b) { return a.r<b.r; } struct Seg_Tree { bool cover; UI l,r,mid; Seg_Tree *ch[2]; }*root; inline Seg_Tree *New(UI l,UI r) { R Seg_Tree *p=new Seg_Tree; p->cover=0; p->l=l; p->r=r; p->mid=((long long)l+r)>>1; p->ch[1]=p->ch[0]=NULL; return p; } bool query(Seg_Tree *p,UI l,UI r) { if(p->cover)return 1; if(l<=p->l&&p->r<=r)return p->cover; R bool ans=1; if(l<=p->mid) { if(!p->ch[0])return 0; else ans&=query(p->ch[0],l,r); } if(p->mid<r) { if(!p->ch[1])return 0; else ans&=query(p->ch[1],l,r); } return ans; } void ins(Seg_Tree *p,UI l,UI r) { if(p->cover)return; if(l<=p->l&&p->r<=r) { p->cover=1; return; } if(l<=p->mid) { if(!p->ch[0]) p->ch[0]=New(p->l,p->mid); ins(p->ch[0],l,r); } if(p->mid<r) { if(!p->ch[1]) p->ch[1]=New(p->mid+1,p->r); ins(p->ch[1],l,r); } if(p->ch[0]&&p->ch[1])p->cover=p->ch[0]->cover&p->ch[1]->cover; } inline void Init() { scanf("%d",&n); for(R int i=1;i<=n;i++) { R int x,r; scanf("%d%d",&x,&r); o[i].x=(long long)x+2000000005; o[i].r=r; } sort(o+1,o+n+1,comp); root=New(1,4000000010LL); } inline void work() { R int ans=1; for(int i=1;i<=n;i++) { ++ans; if(query(root,o[i].x-o[i].r,o[i].x+o[i].r))++ans; ins(root,o[i].x-o[i].r,o[i].x+o[i].r); } printf("%d",ans); } int main() { Init(); work(); return 0; }
以上是关于NOIP模拟赛天下神凡 动态开点线段树的主要内容,如果未能解决你的问题,请参考以下文章