BZOJ4561: [JLoi2016]圆的异或并 计算几何+treap
因为本题保证两圆之间只有相包含或相离(不用担心两圆重合 因为我没有RE) 所以每个圆之间的相对位置是确定的 也就是可以按极角排序的, 所以可以按横坐标排序后 扫描同时用treap维护加圆删圆(即遇到圆的左边界加圆 遇到又边界删圆 treap中的节点是某个圆的上半部分 或某个圆的下半部分)
具体见其他人的博客 我只想说 我颓废两天、要来的数据全A交上去还是RE 的原因是 windows的rand是32767内的 而BZOJ是Linux也就是说 int x=rand()*rand()=RE; 好的GG、WP&HF *&%……#&*%……&@#* 恩 转C没转完整的我 的悲剧
贴代码吧 。。
1 #include <bits/stdc++.h> 2 #define LL long long 3 #define eps 0.000000001 4 #define N 400005 5 using namespace std; 6 struct blu{int l,r,s,w,h;}a[N]; 7 struct bla{int x,d;}c[N]; 8 int rt,n; LL ans,x,z,r[N],u[N],v[N]; 9 bool cm(bla a,bla b){return a.x<b.x||a.x==b.x&&a.d<b.d;} 10 void up(int o){a[o].s=a[a[o].l].s+a[a[o].r].s+a[o].w;} 11 void ll(int &o){ 12 int k=a[o].r; a[o].r=a[k].l; a[k].l=o; up(o); up(k); o=k; 13 } 14 void rr(int &o){ 15 int k=a[o].l; a[o].l=a[k].r; a[k].r=o; up(o); up(k); o=k; 16 } 17 void add(int &o,int t){ 18 if (!o){a[o=t].s=a[o].w; return;} 19 long double k=sqrt(r[o]*r[o]-(u[o]-x)*(u[o]-x)); 20 k=o>n?v[o]+k:v[o]-k; 21 if (z<k-eps) add(a[o].l,t); else add(a[o].r,t); 22 if (a[a[o].l].h>a[o].h) rr(o); else 23 if (a[a[o].r].h>a[o].h) ll(o); else up(o); 24 } 25 void del(int &o,int t){ 26 if (o==t){ 27 if (!a[o].l&&!a[o].r) {o=0;return;} 28 if (a[a[o].l].h>a[a[o].r].h){ 29 rr(o); del(a[o].r,t); 30 }else{ 31 ll(o); del(a[o].l,t); 32 } 33 up(o); return; 34 } 35 long double k=sqrt(r[o]*r[o]-(u[o]-x)*(u[o]-x)); 36 k=o>n?v[o]+k:v[o]-k; 37 if (z<k-eps||abs(z-k)<=eps&&t<=n) del(a[o].l,t); else del(a[o].r,t); 38 up(o); 39 } 40 int qiu(int o){ 41 if (!o) return 0; 42 long double k=sqrt(r[o]*r[o]-(u[o]-x)*(u[o]-x)); 43 k=o>n?v[o]+k:v[o]-k; 44 if (z<k-eps) return qiu(a[o].l); 45 return qiu(a[o].r)+a[o].w+a[a[o].l].s; 46 } 47 int main(){ 48 srand(23); scanf("%d",&n); 49 for (int i=1;i<=n;++i) { 50 scanf("%lld%lld%lld",&u[i],&v[i],&r[i]); 51 u[i+n]=u[i]; v[i+n]=v[i]; r[i+n]=r[i]; 52 c[i].d=i; c[i].x=u[i]-r[i]; 53 c[i+n].d=-i; c[i+n].x=u[i]+r[i]; 54 } 55 sort(c+1,c+n+n+1,cm); 56 for (int i=1;i<=n;++i) a[i].w=1,a[i+n].w=-1; 57 for (int i=1;i<=n+n;++i) a[i].h=rand()+1; //←就是这 我写了rand()*rand() 58 for (int i=1;i<=n+n;++i) 59 if (c[i].d>0) { 60 x=c[i].x; z=v[c[i].d]; 61 ans+=r[c[i].d]*r[c[i].d]*(qiu(rt)&1?-1:1); 62 add(rt,c[i].d); add(rt,c[i].d+n); 63 }else{ 64 x=c[i].x; z=v[-c[i].d]; 65 del(rt,-c[i].d); del(rt,-c[i].d+n); 66 } 67 printf("%lld",ans); 68 return 0; 69 }
转载请标明出处 http://www.cnblogs.com/cyz666/