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

 

I - Intersection

 HDU - 5120 

求圆环面积交:

两个大圆面积交 - 一个大一个小面积交   -  一个大一个小面积交   + 两个小的面积交

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

 

posted @ 2021-01-18 09:55  无声-黑白  阅读(93)  评论(0编辑  收藏  举报