首页 > 代码库 > 2014.10.31我出的模拟赛【天神下凡】

2014.10.31我出的模拟赛【天神下凡】

天神下凡(god.*)

背景

  Czy找到宝藏获得屠龙宝刀和神秘秘籍!现在他要去找经常ntr他的Jmars报仇……

题目描述

Czy学会了一招“堕天一击”,他对一个地点发动堕天一击,地面上就会留下一个很大的圆坑。圆坑的周围一圈能量太过庞大,因此无法通过。所以每次czy发动技能都会把地面分割。Jmars拥有好大好大的土地,几十眼都望不到头,所以可以假设土地的大小是无限大。现在czy对他发动了猛烈的攻击,他想知道在泽宇攻击之后他的土地被切成几份了?

Czy毕竟很虚,因此圆心都在x坐标轴上。另外,保证所有圆两两之间不会相交。

格式

输入第一行为整数n,表示czy放了n次堕天一击。

接下来n行,每行两个整数x[i]r[i]。表示在坐标(x[i] , 0)放了一次堕天一击,半径为r[i]

输出一行,表示地面被分割成几块。

样例输入

4

7 5

-9 11

11 9

0 20

样例输出

6

数据范围

对于30%数据,n<=5000

对于100%数据,1<=n<=300000,-10^9<=x[i]<=10^9,1<=r[i]<=10^9.

 

原题vijos1883 http://www.cnblogs.com/zhber/p/4064916.html

考虑圆对答案的贡献:当它并没有被沿着直径分开的时候,对答案的贡献是1。如果被分开贡献是2。所以按r从小到大排序,把树的左右端点离散,用一个线段树维护区间是否被覆盖。如果已经被覆盖,贡献是2,否则贡献是1

  1 #include<cstdio>  2 #include<iostream>  3 #include<cstring>  4 #include<cstdlib>  5 #include<algorithm>  6 #include<cmath>  7 #include<queue>  8 #include<deque>  9 #include<set> 10 #include<map> 11 #include<ctime> 12 #define LL long long 13 #define N 500010 14 #define mod 1000007 15 using namespace std; 16 struct yuan{int x,r,left,right;}a[N];bool operator <(const yuan &a,const yuan &b){return a.r<b.r;} 17 struct ha{int v,next,rnk;}hash[3*N];bool operator <(const ha &a,const ha &b){return a.v<b.v;} 18 struct segtree{int l,r;bool mark;}tree[8*N]; 19 LL ans; 20 int n; 21 int head[mod]; 22 int cnt,mx; 23 int from[3*N]; 24 inline int ins(int w) 25 { 26     int u=w%mod;if (u<0)u+=mod; 27     for (int i=head[u];i;i=hash[i].next) 28       if (hash[i].v==w) return i; 29     hash[++cnt].v=w; 30     hash[cnt].next=head[u]; 31     hash[cnt].rnk=cnt; 32     head[u]=cnt; 33     return cnt; 34 } 35 inline void build(int now,int l,int r) 36 { 37     tree[now].l=l; 38     tree[now].r=r; 39     if (l==r)return; 40     int mid=(l+r)>>1; 41     build(now<<1,l,mid); 42     build(now<<1|1,mid+1,r); 43 } 44 inline void update(int k) 45 {tree[k].mark=tree[k<<1].mark&&tree[k<<1|1].mark;} 46 inline bool query(int now,int l,int r) 47 { 48     int x=tree[now].l,y=tree[now].r; 49     if (x==l&&y==r)return tree[now].mark; 50     int mid=(x+y)>>1; 51     if (r<=mid)return query(now<<1,l,r); 52     else if (l>mid)return query(now<<1|1,l,r); 53     else return query(now<<1,l,mid)&&query(now<<1|1,mid+1,r); 54 } 55 inline void mark(int now,int l,int r) 56 { 57     int x=tree[now].l,y=tree[now].r; 58     if (x==l&&y==r) 59     { 60         tree[now].mark=1; 61         return; 62     } 63     int mid=(x+y)>>1; 64     if (r<=mid)mark(now<<1,l,r); 65     else if (l>mid)mark(now<<1|1,l,r); 66     else 67     { 68         mark(now<<1,l,mid); 69         mark(now<<1|1,mid+1,r); 70     } 71     update(now); 72 } 73 int main() 74 { 75     //freopen("god7.in","r",stdin); 76     //freopen("god .ans","w",stdout); 77     scanf("%d",&n); 78     for(int i=1;i<=n;i++) 79     { 80         scanf("%d",&a[i].x); 81         scanf("%d",&a[i].r); 82         a[i].left=ins(a[i].x-a[i].r); 83         a[i].right=ins(a[i].x+a[i].r); 84     } 85     sort(hash+1,hash+cnt+1); 86     for (int i=1;i<=cnt;i++) 87       from[hash[i].rnk]=i; 88     for (int i=1;i<=n;i++) 89     { 90       a[i].left=from[a[i].left]; 91       a[i].right=from[a[i].right]; 92       if (a[i].right>mx)mx=a[i].right; 93     } 94     sort(a+1,a+n+1); 95     build(1,1,mx); 96     ans=n+1; 97     for (int i=1;i<=n;i++) 98       { 99           if (query(1,a[i].left,a[i].right-1))ans++;100           mark(1,a[i].left,a[i].right-1);101       }102     printf("%I64d\n",ans);103 }
View Code

2014.10.31我出的模拟赛【天神下凡】