2020寒假 Day-2
2020 China Collegiate Programming Contest Changchun Onsite
F. Strange Memory
直接想法是 启发式合并:拿重儿子合并轻儿子,每发现 $a_i $ ^$ a_j = a_{lca(i,j)}$ 就把$i $^$ j$ 加入答案。
但直接合并是$O(n^2)$,考虑开个数组 $cnt[val][i][j]$ 表示权值为val的数的第 $i$ 位 为 $j$ 的个数。
直接启发式合并即可。
#include<bits/stdc++.h> using namespace std; const int N=1e5+500; #define pb push_back typedef long long ll; int a[N]; int n; ll ans=0; vector<int>G[N]; int size[N],son[N]; int cnt[N*12][22][2]; int Son; void dfs_size(int u,int fa){ size[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa)continue; dfs_size(v,u); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void Count(int u,int fa,int num){ int val=a[u]^num; for(int i=0;i<=20;i++){ ans+=(1ll<<i)*cnt[val][i][!((u>>i)&1)]; } for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa||v==Son)continue; Count(v,u,num); } } void add(int u,int fa,int keep){ for(int i=0;i<=20;i++){ cnt[a[u]][i][(u>>i)&1]+=keep; } for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa||v==Son)continue; add(v,u,keep); } } void dfs_ans(int u,int fa,bool keep){ for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa||v==son[u])continue; dfs_ans(v,u,false); } if(son[u]){ dfs_ans(son[u],u,true); Son=son[u]; } for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa||v==son[u])continue; Count(v,u,a[u]); add(v,u,1); } Son=0; for(int i=0;i<=20;i++){ cnt[a[u]][i][(u>>i)&1]++; } if(keep==0){ add(u,fa,-1); } } int main(){ cin>>n; memset(son,0,sizeof son); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1,u,v;i<n;i++){ scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs_size(1,-1); dfs_ans(1,-1,0); cout<<ans<<endl; // system("pause"); return 0; }
I - Intersection
求圆环面积交:
两个大圆面积交 - 一个大一个小面积交 - 一个大一个小面积交 + 两个小的面积交
c#include<bits/stdc++.h> using namespace std; #define pb push_back const int N=1e5+500; double pi=acos(-1.0); typedef long long ll; typedef double db; db eps=1e-6; int sgn(db x){ if(fabs(x)<eps)return 0; else return x<0?-1:1; } struct Point{ db x,y; Point(double X=0,double Y=0){x=X;y=Y;} Point operator +(Point B){return Point(x+B.x,y+B.y);} Point operator -(Point B){return Point(x-B.x,y-B.y);} Point operator *(double k){return Point(x*k,y*k);} Point operator /(double k){return Point(x/k,y/k);} friend bool operator<(Point A,Point B){ return sgn(A.x-B.x)<0||(sgn(A.x-B.x)==0&&sgn(A.y-B.y)<0); } friend bool operator==(Point A,Point B){ return sgn(A.x-B.x)==0&&sgn(A.y-B.y)==0; } }; typedef Point Vector; double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;} db Distance(Point A,Point B){return hypot(A.x-B.x,A.y-B.y);} double intersect(double x1,double y1,double r1,double x2,double y2,double r2){ double s,temp,p,l,ans; l=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); if(l>=r1+r2) ans=0; else if(l<=abs(r1-r2)){ if(r1<=r2) ans=pi*r1*r1; else ans=pi*r2*r2; } else{ p=(l+r1+r2)/2; s=2*sqrt(p*(p-l)*(p-r1)*(p-r2)); if(r1>r2){ temp=x1;x1=x2;x2=temp; temp=y1;y1=y2;y2=temp; temp=r1;r1=r2;r2=temp; } ans=acos((r1*r1+l*l-r2*r2)/(2*r1*l))*r1*r1+acos((r2*r2+l*l-r1*r1)/(2*r2*l))*r2*r2-s; } return ans; } int main(){ int t;cin>>t; int kase=0; while(t--){ db r,R; scanf("%lf %lf",&r,&R); Point A,B; scanf("%lf %lf",&A.x,&A.y); scanf("%lf %lf",&B.x,&B.y); db ans=intersect(A.x,A.y,R,B.x,B.y,R)-intersect(A.x,A.y,R,B.x,B.y,r)-intersect(A.x,A.y,r,B.x,B.y,R)+ intersect(A.x,A.y,r,B.x,B.y,r); printf("Case #%d: %.6lf\n",++kase,ans); } // system("pause"); return 0; }
想的太多,做的太少;