[vijos1883]月光的魔法<递归>

题目链接:https://vijos.org/p/1883

这道题还有另外一种版本叫天神下凡,属于模拟题,可是模拟题数据太水以至于模拟题A了都不一定在vijos上A。。。。

在模拟题里我用的是一种类似扫描线的方式,完美AC,然后在vijos上就是只能过2组

最后经同学提点改为递归才A了

 

这道题我们把圆看成线段,所以这题就是线段覆盖,然后答案是被完全覆盖的线段数+所有线段数+1

被完全覆盖的线段的数量就用递归找,不断的找被当前线段完全包含的线段,然后判断是否在里面

然后这道题有一种特殊情况可以不用执行程序,就是所有圆都是同心圆的时候,因为这种状态只存在重合和包含(本题重合不算完全覆盖),直接输出圆的数量+1即可

 

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define maxn 300005
 7 #define ll long long
 8 using namespace std;
 9 
10 ll n,cnt,can,ans;
11 struct node{
12     ll l,r;
13 }e[maxn];
14 
15 ll read(){
16     ll xx=0;ll ff=1;char ch=getchar();
17     while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
18     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
19     return xx*ff;
20 }
21 
22 int cmp(node a,node b){
23     if(a.l==b.l ){
24         return a.r>b.r;
25     }return a.l<b.l;
26 }
27 
28 int t;
29 int check (ll id){
30     int now=e[id].l,add=1,ret=0;
31     while(t!=n+1&&e[t].r<=e[id].r){
32         if(e[t].l!=now)add=0;
33         now=e[t].r;
34         ret+=check(t++);
35     }
36     if(now!=e[id].r )add=0;
37     return 1+ret+add;
38 }
39 
40 int main(){
41     n=read();
42     for(ll i=1;i<=n;i++){
43         ll x,R;
44         x=read();R=read();
45         e[i].l=x-R;e[i].r=x+R;
46         if(cnt==0)cnt=x;
47         if(cnt!=x)can=1;
48     }
49     if(!can){cout<1;return 0;    }//同一个圆心可以不管了
50     sort(e+1,e+n+1,cmp);t=1;
51     while(t!=n+1){
52         ans+=check(t++);
53     } ans=ans+1;
54     cout<<ans;
55 }
View Code

 

 

 

然后这道题还有一个解法就是线段树,因为不存在相交的情况,所以不需要使用lazy标记,没有lazy标记的线段树就很简单了

但是要注意一点就是这些左右端点在坐标轴上,坐标轴有可能很大,所以要用到离散化

 

你可能感兴趣的:([vijos1883]月光的魔法<递归>)