[BZOJ 4418][Shoi2013]扇形面積並(樹狀數組+二分)
阿新 • • 發佈:2017-05-19
continue define getchar getc amp -1 n) long sin
Description
給定N個同心的扇形,求有多少面積,被至少K個扇形所覆蓋。Solution
打開發現是計算幾何還以為是看錯題號了QwQ
其實就是遇到一條開始的邊+1,遇到一條結束的邊-1,a1>a2的話就再加上一個完整的圓
計算每一部分只需要找到第cnt-k+1大的半徑,在樹狀數組上二分就好了
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define MAXN 100005 usingnamespace std; typedef long long LL; int n,m,k,tot=0,c[MAXN]; 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*10+c-‘0‘;c=getchar(); } return x*f; } struct Node {int r,a,f; Node(int r=0,int a=0,int f=0):r(r),a(a),f(f){} bool operator < (const Node& x) const {return a<x.a;} }data[400005]; int lowbit(int x){return x&-x;} void add(int pos,int x) { while(pos<=MAXN) { c[pos]+=x; pos+=lowbit(pos); } }int solve(int sum) { int x=0,now=0; for(int i=(1<<20);i;i>>=1) if(x+i<=MAXN&&now+c[x+i]<sum) now+=c[x+i],x+=i; return x+1; } int main() { n=read(),m=read(),k=read(); for(int i=1;i<=n;i++) { int r=read(),a1=read(),a2=read(); data[++tot]=Node(r,a1,1); data[++tot]=Node(r,a2,-1); if(a1>a2) { data[++tot]=Node(r,-m,1); data[++tot]=Node(r,m,-1); } } sort(data+1,data+1+tot); LL ans=0;int cnt=0; for(int i=1;i<tot;i++) { add(data[i].r,data[i].f); cnt+=data[i].f; if(cnt-k+1<=0)continue; int t=solve(cnt-k+1); ans+=1LL*t*t*(data[i+1].a-data[i].a); } printf("%lld\n",ans); return 0; }
[BZOJ 4418][Shoi2013]扇形面積並(樹狀數組+二分)