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 }
Saber

 

posted @ 2017-02-27 15:55  cyz666  阅读(195)  评论(0编辑  收藏  举报