https://www.hackerrank.com/contests/w31/challenges
Accurate Sorting 检查每个数字距离原位是否都不超过1
Zero-One Game 计算可以被删去的数字个数
Spanning Tree Fraction 最优比率生成树,分数规划+Kruscal
Colliding Circles 算出两两圆之间最后被合并的概率,由期望的线性性计算对答案的贡献
#include<bits/stdc++.h> typedef long double ld; int n,k,r[100007]; int main(){ scanf("%d%d",&n,&k); long long s1=0,s2=0; for(int i=0;i<n;++i)scanf("%d",r+i),s1+=r[i],s2+=r[i]*r[i]; ld p=1; for(int i=n;i>n-k;--i){ long long a=1ll*i*(i-1); p=p*ld(a-2)/ld(a); } printf("%.12Lf",acos(-1)*(s2+(s1*s1-s2)*(1-p))); return 0; }
Nominating Group Leaders 权值分块维护莫队,bzoj原题
#include<bits/stdc++.h> const int N=1e5+7; int T,n,m,a[N],as[N],id[N],B,t1[N],t2[N]; struct Q{ int l,r,x,I; bool operator<(Q w)const{ if(id[l]!=id[w.l])return id[l]<id[w.l]; if(r!=w.r)return (r<w.r)!=(id[l]&1); return I<w.I; } }qs[N]; int cnt[N],*l1[N],*l2[N],*l3[N],*l4[N],*r4[N]; int mem[N*5],*mp; void ins(int x,int t){ if(t){ int a=l1[x][t]; ++l2[t][a]; ++l3[t][a>>8]; } } void del(int x,int t){ if(t){ int a=l1[x][t]; --l2[t][a]; --l3[t][a>>8]; } } int find(int t){ for(int i=0;i<t2[t];i+=256)if(l3[t][i>>8]){ int j=i; while(!l2[t][j])++j; return l4[t][j]; } return -1; } void ins(int x){ del(x,cnt[x]); ins(x,++cnt[x]); } void del(int x){ del(x,cnt[x]); ins(x,--cnt[x]); } int main(){ for(scanf("%d",&T);T;--T){ scanf("%d",&n); for(int i=0;i<n;++i){ scanf("%d",a+i); } mp=mem; memset(mem,0,sizeof(mem)); memset(cnt,0,sizeof(cnt)); memset(t1,0,sizeof(t1)); memset(t2,0,sizeof(t2)); for(int i=0;i<n;++i)++t1[a[i]]; for(int i=0;i<n;++i)l1[i]=mp-1,mp+=t1[i]; for(int i=0;i<n;++i){ for(int j=1;j<=t1[i];++j){ l1[i][j]=t2[j]++; } } for(int i=1;i<=n;++i){ l4[i]=r4[i]=mp,mp+=t2[i]; l3[i]=mp,mp+=t2[i]; l2[i]=mp,mp+=t2[i]; } for(int i=0;i<n;++i){ for(int j=1;j<=t1[i];++j){ *r4[j]++=i; } } scanf("%d",&m); B=(n+1)/sqrt(m+1)+1; for(int i=0;i<n;++i)id[i]=i/B; for(int i=0;i<m;++i){ scanf("%d%d%d",&qs[i].l,&qs[i].r,&qs[i].x); qs[i].I=i; } std::sort(qs,qs+m); int L=0,R=-1; for(int i=0;i<m;++i){ int l=qs[i].l,r=qs[i].r; while(L>l)ins(a[--L]); while(R<r)ins(a[++R]); while(L<l)del(a[L++]); while(R>r)del(a[R--]); as[qs[i].I]=find(qs[i].x); } for(int i=0;i<m;++i)printf("%d\n",as[i]); } return 0; }
Split Plane 由欧拉定理,线段划分出的联通块数=边数-点数+1+线段构成的联通块个数,扫描线处理一下,要开long long !!!
具体实现:横竖各扫一次,计算每条线段与其他线段的交点个数,特判一下端点
用可持久化线段树和并查集维护线段构成的联通块,支持插入、删除一条与扫描线垂直的线段,将当前区间内的线段标记为并起来,细节较多,具体见代码
#include<bits/stdc++.h> #define int long long const int N=1e5+7; struct seg{ int x,l,r; bool operator<(seg w)const{return x!=w.x?x<w.x:l<w.l;} }s1[N],s2[N],ss[N]; int p1,p2,ans,V,E,C; int T,n,xs[N*2],ys[N*2],xp=0,yp=0; void gx(int&x){x=std::lower_bound(xs,xs+xp,x)-xs;} void gy(int&x){x=std::lower_bound(ys,ys+yp,x)-ys;} void rb(seg*a,int&ap){ std::sort(a,a+ap); int sp=0; for(int i=0,j=0;i<ap;i=j){ while(j<ap&&a[i].x==a[j].x)++j; ss[sp++]=a[i++]; for(;i<j;++i){ if(ss[sp-1].r<a[i].l)ss[sp++]=a[i]; else if(ss[sp-1].r<a[i].r)ss[sp-1].r=a[i].r; } } for(int i=0;i<sp;++i)a[i]=ss[i]; ap=sp; } struct ev{ int tp,x,a,b; bool operator<(ev e)const{return x!=e.x?x<e.x:tp<e.tp;} }e[N*10]; int t0[N*2],bit[N*2]; void add(int w,int a){ if(t0[w]==0||t0[w]+a==0)for(int x=w+1;x<N*2;x+=x&-x)bit[x]+=a; t0[w]+=a; } int sum(int w){ int s=0; for(++w;w;w-=w&-w)s+=bit[w]; return s; } int ch[N*100][2],p,ws[N],f[N*100],pv; bool fd[N*100],ed[N*100]; int gf(int x){ int a=x,c; while(x!=f[x])x=f[x]; while(x!=f[a])c=f[a],f[a]=x,a=c; return x; } int newnode(){ ++p; ch[p][0]=ch[p][1]=0; f[p]=p; fd[p]=0; ed[p]=0; return p; } void mg(int a,int b){ f[gf(a)]=gf(b); } void dfs(int w){ if(fd[w])return; fd[w]=1; for(int d=0;d<2;++d)if(ch[w][d]){ mg(w,ch[w][d]); dfs(ch[w][d]); } } void find(int w,int L,int R,int l,int r){ if(!w)return; if(l<=L&&R<=r){ if(pv)mg(w,pv); dfs(w); pv=w; return; } int M=L+R>>1; if(l<=M)find(ch[w][0],L,M,l,r); if(r>M)find(ch[w][1],M+1,R,l,r); } int ins(int w,int L,int R,int x,int y){ int u=newnode(); if(L==R){ ws[y]=u; }else{ int M=L+R>>1; if(x<=M)ch[u][0]=ins(ch[w][0],L,M,x,y),ch[u][1]=ch[w][1]; else ch[u][1]=ins(ch[w][1],M+1,R,x,y),ch[u][0]=ch[w][0]; } return u; } int del(int w,int L,int R,int x){ if(L==R)return 0; int u=newnode(); int M=L+R>>1; if(x<=M)ch[u][0]=del(ch[w][0],L,M,x),ch[u][1]=ch[w][1]; else ch[u][1]=del(ch[w][1],M+1,R,x),ch[u][0]=ch[w][0]; if(!ch[u][0]&&!ch[u][1])return 0; return u; } void cal(seg*a,int ap,seg*b,int bp,bool cc){ memset(t0,0,sizeof(t0)); memset(bit,0,sizeof(bit)); p=0; int rt=newnode(); int ep=0; for(int i=0;i<ap;++i)e[ep++]=(ev){2,a[i].x,a[i].l,a[i].r}; for(int i=0;i<bp;++i){ e[ep++]=(ev){1,b[i].l,b[i].x,i}; e[ep++]=(ev){0,b[i].r+1,b[i].x,i}; } std::sort(e,e+ep); for(int i=0;i<ep;++i){ if(e[i].tp==2){ int s=sum(e[i].b)-sum(e[i].a-1); V+=s; E+=s-1; if(!t0[e[i].a])V+=2,++E; if(!t0[e[i].b])V+=2,++E; if(cc&&s){ pv=0; find(rt,0,262143,e[i].a,e[i].b); --C; } }else if(e[i].tp==1){ add(e[i].a,1); if(cc)rt=ins(rt,0,262143,e[i].a,e[i].b); }else{ add(e[i].a,-1); if(cc)rt=del(rt,0,262143,e[i].a); } } if(cc) for(int i=0;i<bp;++i){ int a=gf(ws[i]); if(!ed[a])ed[a]=1; else --C; } } signed main(){ for(scanf("%lld",&T);T;--T){ scanf("%lld",&n); p1=p2=0; xp=yp=0; for(int i=0,x1,y1,x2,y2;i<n;++i){ scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2); xs[xp++]=x1; xs[xp++]=x2; ys[yp++]=y1; ys[yp++]=y2; if(x1>x2)std::swap(x1,x2); if(y1>y2)std::swap(y1,y2); if(x1==x2)s1[p1++]=(seg){x1,y1,y2}; else if(y1==y2)s2[p2++]=(seg){y1,x1,x2}; } std::sort(xs,xs+xp); xp=std::unique(xs,xs+xp)-xs; std::sort(ys,ys+yp); yp=std::unique(ys,ys+yp)-ys; rb(s1,p1); rb(s2,p2); for(int i=0;i<p1;++i){ gx(s1[i].x); gy(s1[i].l); gy(s1[i].r); } for(int i=0;i<p2;++i){ gy(s2[i].x); gx(s2[i].l); gx(s2[i].r); } V=E=0; C=p1+p2; cal(s1,p1,s2,p2,1); cal(s2,p2,s1,p1,0); // printf("[V=%g E=%d C=%d]",V*.5,E,C); printf("%lld\n",E-V/2+1+C); } return 0; }