题意
https://www.luogu.org/problemnew/show/P3268
思考&别人的思考
包含关系有传递性和自反性,类似于小于号。
对于一条垂直与x轴的直线,有包含关系的圆的交点满足括号序列。如:
因此可以做扫描线。把圆分成上下两端弧,表示扫描线正与这些弧有交点,对于新添加的弧,判断第一个在其上方的弧是上半段还是下半段。若是上半段,则有包含关系;否则为并列关系。
只与小于号,由于我们维护的是与弧的焦点,又因为有交点时,其相对位置不会改变,因此只要维护交点的y坐标即可(只有查询和删除时用得到)。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const ll maxn=2E5+5; 5 ll n,f[maxn]; 6 ll x,y,z,R[maxn],ans; 7 double now; 8 double s(double x) 9 { 10 return x*x; 11 } 12 struct pt 13 { 14 ll x,y,r,id; 15 pt(ll X=0,ll Y=0,ll R=0,ll i=0) 16 { 17 x=X,y=Y,r=R,id=i; 18 } 19 bool operator<(pt A)const 20 { 21 if(x==A.x) 22 return 0; 23 return x<A.x; 24 } 25 }a[maxn*2]; 26 struct node 27 { 28 pt A; 29 ll flag; 30 node(ll x=0,ll y=0,ll z=0,ll gg=0,ll g=0) 31 { 32 A=pt(x,y,z,gg),flag=g; 33 } 34 bool operator<(node x)const 35 { 36 double a=double(A.y)+flag*sqrt(s(double(A.r))-s(now-double(A.x))+0.000001); 37 double b=double(x.A.y)+x.flag*sqrt(s(double(x.A.r))-s(now-double(x.A.x))+0.000001); 38 return a<b; 39 } 40 }; 41 void out(multiset<node>S) 42 { 43 multiset<node>::iterator pt=S.begin(); 44 while(pt!=S.end()) 45 { 46 cout<<(*pt).A.r<<' '<<(*pt).A.x<<" "<<(*pt).A.y<<' '<<(*pt).A.id<<' '<<(*pt).A.y+(*pt).flag*sqrt(s((*pt).A.r)-s(now-(*pt).A.x)+0.001)<<" "<<now<<endl; 47 ++pt; 48 } 49 } 50 int main() 51 { 52 ios::sync_with_stdio(false); 53 cin>>n; 54 for(int i=1;i<=n;++i) 55 { 56 cin>>x>>y>>z; 57 a[2*i-1]=pt(x-z,y,z,i); 58 a[2*i]=pt(x+z,y,z,i+n); 59 f[i]=1; 60 R[i]=z; 61 } 62 sort(a+1,a+2*n+1); 63 // for(int i=1;i<=n*2;++i) 64 // cout<<a[i].id<<' '; 65 // cout<<endl; 66 multiset<node>S; 67 for(int i=1;i<=2*n;++i) 68 { 69 now=a[i].x; 70 if(S.empty()) 71 { 72 // cout<<a[i].x<<' '<<a[i].y<<' '<<a[i].r<<endl; 73 S.insert(node(a[i].x+a[i].r,a[i].y,a[i].r,a[i].id,1)); 74 S.insert(node(a[i].x+a[i].r,a[i].y,a[i].r,a[i].id+n,-1)); 75 } 76 else if(a[i].id<=n) 77 { 78 // cout<<a[i].x<<' '<<a[i].y<<' '<<a[i].r<<"---"<<endl; 79 set<node>::iterator pt=S.upper_bound(node(a[i].x,a[i].y,a[i].r,1)); 80 // cout<<(*pt).A.id<<endl; 81 if(pt==S.end()) 82 { 83 --pt; 84 f[a[i].id]=f[(*pt).A.id]; 85 } 86 else if((*pt).A.id<=n) 87 f[a[i].id]=-f[(*pt).A.id]; 88 else 89 f[a[i].id]=f[(*pt).A.id-n]; 90 S.insert(node(a[i].x+a[i].r,a[i].y,a[i].r,a[i].id,1)); 91 S.insert(node(a[i].x+a[i].r,a[i].y,a[i].r,a[i].id+n,-1)); 92 } 93 else 94 { 95 // cout<<"JJJ"<<a[i].x-a[i].r<<' '<<a[i].y<<" "<<a[i].r<<" "<<a[i].id<<endl; 96 S.erase(node(a[i].x-a[i].r,a[i].y,a[i].r,a[i].id-n,1)); 97 S.erase(node(a[i].x-a[i].r,a[i].y,a[i].r,a[i].id,-1)); 98 // cout<<"CAO"<<S.size()<<endl; 99 } 100 // cout<<"NOW"<<"-----------"<<endl; 101 // out(S); 102 // cout<<endl; 103 } 104 for(int i=1;i<=n;++i) 105 { 106 ans+=s(R[i])*f[i]; 107 // cout<<f[i]<<' '; 108 } 109 // cout<<endl; 110 cout<<ans<<endl; 111 return 0; 112 }