背景
影几欺哄了众生了,天以外——月儿何曾圆缺。
描述
有些东西就如同月光的魔法一般.
Luke是爱着vijos的.他想为自己心爱的东西画些什么——————就画N个圆吧.把它们的圆心都固定在x轴上.圆与圆.为了爱,两两不能相交.为了爱,它们可以互相贴在一起.内切或外切,都是允许的.
vijos的美丽,在于人心.vijos的孩子们,一定能告诉大家:Luke画的圆究竟把平面分割成了多少块?
月光恬美地洒在大地上.Luke知道,如果什么都不画,平面就只有一块.多美呢!Luke知道,只画一个圆,平面就分成了两块.也很美呢!但Luke还是要多画一些的,因为他真的深爱着vijos呢.
格式
输入格式
输入数据第一行:输出一个整数N,1<=N<=300,000.表示圆的个数.
之后N行,每一行有2个整数,x[i]和r[i]表示圆心固定在x[i]的位置,半径为r[i].
-1,000,000,000<=x[i]<=1,000,000,000
1<=r[i]<=1,000,000,000
所有圆都是唯一的,不会出现重叠.
输出格式
输出只有一行,要求输出平面被分割成了多少块.
限制
对于40%的数据:
N<=5000.
对于100%的数据:
1<=N<=300,000;-1,000,000,000<=x[i]<=1,000,000,000;1<=r[i]<=1,000,000,000
题解
线段树的引用,我将圆按半径从大到小排列,用每个圆的编号在线段树上覆盖“该圆所覆盖的x轴”。线段树维护每一段中编号的最小值。之后从半径从小到大,若该圆所覆盖的x轴上编号最小=这个圆的编号,ans+1,否则ans+2.具体是为什么……好像画个图想想就好。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> #define MAXN 300002 #define ll long long using namespace std; int n,b[MAXN<<1],cnt,hs[MAXN<<1],zz; struct yuan{int o,r,L,R;} a[MAXN]; struct tree{int l,r,v,tag;} tr[MAXN*8]; ll ans; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+(ch-'0'); ch=getchar();} return f*x; } bool kp(const yuan &i,const yuan &j) {return i.r>j.r;} void init() { n=read(); //printf("%d\n",n); int i,x,r; for(i=1;i<=n;i++) {a[i].o=read(); a[i].r=read(); //printf("%d %d\n",a[i].o,a[i].r); a[i].L=a[i].o-a[i].r; a[i].R=a[i].o+a[i].r; //printf("%d %d\n",a[i].L,a[i].R); b[++cnt]=a[i].L; b[++cnt]=a[i].R; } sort(b+1,b+cnt+1); hs[1]=b[1]; zz=1; for(i=2;i<=cnt;i++) {if(b[i]!=b[i-1]) hs[++zz]=b[i];} /*for(i=1;i<=zz;i++) printf("%d ",hs[i]); printf("\n"); system("pause");*/ sort(a+1,a+n+1,kp); } //------------------------------------------------------------------------------ void build(int w,int s,int e) { tr[w].l=s; tr[w].r=e; if(s==e) {tr[w].v=1<<30; tr[w].tag=-1; return ;} int mid=(s+e)>>1; build(w<<1,s,mid); build((w<<1)+1,mid+1,e); } int getw(int x) { int s=1,e=zz,mid,w; while(s<=e) {mid=(s+e)>>1; if(hs[mid]>x) e=mid-1; else {w=mid; s=mid+1;} } return w; } void down(int w) { if(tr[w].tag==-1) return; int l=w<<1,r=l+1,t=tr[w].tag; tr[w].tag=-1; tr[l].v=t; tr[l].tag=t; tr[r].v=t; tr[r].tag=t; } void insert(int w,int s,int e,int v) { down(w); int l=tr[w].l,r=tr[w].r; if(s==l&&r==e) {tr[w].v=v; tr[w].tag=v; return ; } int mid=(l+r)>>1; if(e<=mid) insert(w<<1,s,e,v); else if(s>mid) insert((w<<1)+1,s,e,v); else {insert(w<<1,s,mid,v); insert((w<<1)+1,mid+1,e,v);} tr[w].v=min(tr[(w<<1)+1].v,tr[w<<1].v); } int find(int w,int s,int e) { down(w); int l=tr[w].l,r=tr[w].r; if(s==l&&r==e) return tr[w].v; int mid=(l+r)>>1; if(e<=mid) return find(w<<1,s,e); else if(s>mid) return find((w<<1)+1,s,e); else return min(find(w<<1,s,mid),find((w<<1)+1,mid+1,e)); } void work() { int i,s,e; for(i=1;i<=n;i++) {s=getw(a[i].L); e=getw(a[i].R-1); insert(1,s,e,i); } for(i=n;i>=1;i--) {s=getw(a[i].L); e=getw(a[i].R-1); int t=find(1,s,e); //printf("%d\n",t); //system("pause"); if(t<=i) ans++; else ans+=2; } printf("%d\n",ans+1); } int main() { init(); build(1,1,zz); work(); return 0; }