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 }