LOJ P10002 喷水装置 题解

每日一题 day35 打卡

Analysis

先将不符合条件的区间去掉(即半径小于W,不然宽度无法符合),将符合条件的按区间存入节点中。区间的左边界是x-sqrt(r*r-W*W/4.0),要计算x轴的最小长度,而不是x-r。然后将区间按照左边界从小到大排序,依次找到能够覆盖L点的最大右端点。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define int long long
 7 #define maxn 15000+10
 8 #define rep(i,s,e) for(register int i=s;i<=e;++i)
 9 using namespace std;
10 inline int read()
11 {
12     int x=0;
13     bool f=1;
14     char c=getchar();
15     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
16     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
17     if(f) return x;
18     return 0-x;
19 }
20 inline void write(int x)
21 {
22     if(x<0){putchar('-');x=-x;}
23     if(x>9)write(x/10);
24     putchar(x%10+'0');
25 }
26 int T,n,L,W,num,ans;
27 struct node
28 {
29     double x,y;
30 }reg[maxn];
31 bool cmp(node x,node y)
32 {
33     return x.x<y.x;
34 }
35 signed main()
36 {
37     T=read();
38     while(T--)
39     {
40         num=0;
41         memset(reg,0,sizeof(reg));
42         n=read();L=read();W=read();
43         rep(i,1,n) 
44         {
45             int x=read(),r=read();
46             if(r<=W/2) continue;
47             reg[++num].x=x-sqrt((double)r*r-(double)W*W/4.0);
48             reg[num].y=x+sqrt((double)r*r-(double)W*W/4.0);
49         }
50         sort(reg+1,reg+num+1,cmp);
51         int cnt=1,ans=0;
52         double now=0;
53         while(now<L)
54         {
55             ++ans;
56             double re=now;
57             while(reg[cnt].x<=re&&cnt<=num)
58             {
59                 if(now<reg[cnt].y) now=reg[cnt].y;
60                 ++cnt;
61             }
62             if(re==now&&now<L)
63             {
64                 ans=-1;
65                 break;
66             }
67         }
68         write(ans);
69         putchar('
');
70     }
71     return 0;
72 }

请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/11842393.html