1. 程式人生 > >BZOJ4561 JLOI2016圓的異或並(掃描線+平衡樹)

BZOJ4561 JLOI2016圓的異或並(掃描線+平衡樹)

  考慮一條掃描線從左到右掃過這些圓。觀察某一時刻直線與這些圓的交點,可以發現構成一個類似括號序列的東西,括號的包含關係與圓的包含關係是相同的。並且當掃描線逐漸移動時,括號間的相對順序不變。於是考慮用set維護這個括號序列,插入時統計被包含層數。這隻需要查詢後繼括號,如果是右括號則被該括號包含,答案為該括號次數+1,否則處於同一層,答案與該括號相同。

  bzoj大概又出了一些奇怪的精度問題,用long double才過。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include
<cstring> #include<algorithm> #include<set> #include<cassert> using namespace std; #define ll long long #define N 200010 #define double long double char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return
c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,cur,ans[N]; const double eps=1E-6
; ll tot; double pos(int a,int b,int r,int op){return b+op*(sqrt(1ll*r*r-1ll*(cur-a)*(cur-a))+eps);} struct data { int x,y,r,i,op; bool operator <(const data&a) const { return pos(x,y,r,op)<pos(a.x,a.y,a.r,a.op); } }a[N<<1]; multiset<data> q; bool cmp(const data&a,const data&b) { return a.x+a.op*a.r<b.x+b.op*b.r; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4561.in","r",stdin); freopen("bzoj4561.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].r=read(),a[i].op=-1,a[i].i=i; for (int i=n+1;i<=n+n;i++) a[i].x=a[i-n].x,a[i].y=a[i-n].y,a[i].r=a[i-n].r,a[i].op=1,a[i].i=a[i-n].i; sort(a+1,a+n+n+1,cmp); for (int i=1;i<=n+n;i++) { cur=a[i].x+a[i].op*a[i].r; if (a[i].op==1) q.erase((data){a[i].x,a[i].y,a[i].r,a[i].i,-1}),q.erase((data){a[i].x,a[i].y,a[i].r,a[i].i,1}); else { q.insert((data){a[i].x,a[i].y,a[i].r,a[i].i,-1}),q.insert((data){a[i].x,a[i].y,a[i].r,a[i].i,1}); set<data>::iterator it=q.find((data){a[i].x,a[i].y,a[i].r,a[i].i,1}); it++;if (it!=q.end()) ans[a[i].i]=(*it).op==1?ans[(*it).i]^1:ans[(*it).i]; if (ans[a[i].i]) tot-=1ll*a[i].r*a[i].r;else tot+=1ll*a[i].r*a[i].r; } } cout<<tot; return 0; }