题意

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 }
View Code

 

 posted on 2019-05-06 19:57  GreenDuck  阅读(232)  评论(0编辑  收藏  举报