cf round #418 div2 D. An overnight dance in discotheque(贪心)

题目链接:http://codeforces.com/contest/814/problem/D

分析:感觉这题挺综合的,写了好久才写出来。。首先由于圆之间只有外离、内含和相切三种情况,可以将包含的圆看作孩子,得到一棵树(也可能是森林,互不影响,分开做就行了),记Q[i]为圆i包含的面积(带符号,已经减去了孩子的面积),然后从根开始考虑,

如果Q[i]<0,把它和它所包含的圆,全部换一边,Q[i]不会更小,因此可以贪心做,具体实现有点麻烦。。排序最好用间接排,不然会很麻烦而且空间很大。。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<stack>
  7 using namespace std;
  8 const int maxn=1005;
  9 const double pi=3.1415926535897932384626433832795;
 10 int n,belong[maxn],r[maxn],de[maxn];
 11 typedef long long ll;
 12 ll Q[maxn];
 13 struct circle{
 14     int x,y,r;
 15     int depth;
 16 }c[maxn];
 17 bool Cmp_r(int i,int j){
 18     return c[i].r>c[j].r;
 19 }
 20 bool Cmp_depth(int i,int j){
 21     return c[i].depth>c[j].depth;
 22 }
 23 bool Is_child(int fa,int child){
 24     if((ll)(c[fa].x-c[child].x)*(c[fa].x-c[child].x)+(ll)(c[fa].y-c[child].y)*(c[fa].y-c[child].y)<=(ll)(c[fa].r-c[child].r)*(c[fa].r-c[child].r))
 25         return true;
 26     return false;
 27 }
 28 vector<int> v[maxn];
 29 stack<int> p[maxn];
 30 void build(){
 31     sort(r,r+n,Cmp_r);
 32     for(int l=n-1;l>=0;l--){
 33         int &i=r[l];
 34         for(int ll=0;ll<l;ll++){
 35             int &j=r[ll];
 36             if(i!=j&&Is_child(j,i)){
 37                 p[i].push(j);
 38             }
 39         }
 40         for(int ll=l-1;ll>=0;ll--){
 41             int &j=r[ll];
 42             if(Is_child(j,i)){
 43                 v[j].push_back(i);
 44                 break;
 45             }
 46         }
 47     }
 48 }
 49 void dfs(int start){
 50     for(int i=0;i<v[start].size();i++){
 51         c[v[start][i]].depth=c[start].depth+1;
 52         dfs(v[start][i]);
 53     }
 54 }
 55 void Change(int k,int depth_fa){
 56     belong[k]=-belong[k];
 57     if((c[k].depth+2)%2==(depth_fa+2)%2)
 58         Q[k]=-Q[k];
 59     c[k].depth=depth_fa+1;
 60     for(int i=0;i<v[k].size();i++)
 61         Change(v[k][i],c[k].depth);
 62 }
 63 int main(){
 64     //freopen("e:\\in.txt","r",stdin);
 65     scanf("%d",&n);
 66     for(int i=0;i<n;i++){
 67         scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
 68         r[i]=i;
 69         de[i]=i;
 70     }
 71     build();
 72     for(int i=0;i<n;i++){
 73         if(p[i].empty()){
 74             c[i].depth=0;
 75             dfs(i);
 76         }
 77     }
 78     sort(de,de+n,Cmp_depth);
 79     for(int l=0;l<n;l++){
 80         int &i=de[l];
 81         Q[i]=(ll)c[i].r*c[i].r;
 82         if(c[i].depth%2)Q[i]=-Q[i];
 83         for(int j=0;j<v[i].size();j++)
 84             Q[i]+=Q[v[i][j]];
 85     }
 86     memset(belong,-1,sizeof(belong));
 87     ll sum=0;
 88     for(int i=0;i<n;i++){
 89         if(p[i].empty())
 90             sum+=Q[i];
 91     }
 92     for(int l=0;l<n;l++){
 93         int &i=r[l];
 94         if(c[i].depth==0)continue;
 95         if(Q[i]<0){
 96             int fa=p[i].top();
 97             Q[fa]-=Q[i];
 98             while(!p[i].empty()&&belong[fa]==belong[i]){
 99                 p[i].pop();
100                 if(!p[i].empty())
101                     fa=p[i].top();
102             }
103             if(p[i].empty()){
104                 Change(i,-1);
105             }else{
106                 Q[fa]+=Q[i];
107                 Change(i,c[fa].depth);
108             }
109             if(Q[i]>0)
110                 sum+=2*Q[i];
111         }
112     }
113     printf("%.8f\n",(double)sum*pi);
114     return 0;
115 }

 

posted @ 2017-07-19 22:50  7391_KID  阅读(198)  评论(0编辑  收藏  举报