【BZOJ4418】[Shoi2013]扇形面积并
Description
给定N个同心的扇形,求有多少面积,被至少K个扇形所覆盖。
Input
第一行是三个整数n,m,k。n代表同心扇形的个数,m用来等分 [-π,π]的弧度。
从第二行开始的n行,每行三个整数r,a1,a2。描述了一个圆心在原点的扇形,半径为r,圆心角是从弧度πa1/m到πa2/m,a1可能大于a2,逆时针扫过的区域为该扇形面积。
Output
输出一个整数ans,至少被K个扇形所覆盖的总面积等于π/2m×ans
保证答案不超过2^63-1
Sample Input
【输入样例1】
3 8 2
1 -8 8
3 -7 3
5 -5 5
【输入样例2】
2 4 1
4 4 2
1 -4 4
Sample Output
【输出样例1】
76
【输出样例2】
98
HINT
对于100%的数据,1≤n≤10^5, 1≤m≤10^6,1≤k≤5000,1≤ri≤10^5,-m≤a1,a2≤m
题解:现将扇形掰开变成矩形,然后用扫描线处理,每个矩形都改成差分的形式。由于对于任意一条与x轴垂直的先,里面的点被覆盖的层数一定不会比外面少,所以我们可以在线段树上二分,时间复杂度$O(nlogr)$。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=100010; typedef long long ll; int n,m,tot,R,K; int s[maxn<<2]; ll ans; struct node { int x,y,k; node() {} node(int a,int b,int c) {x=a,y=b,k=c;} }p[maxn<<2]; bool cmp(const node &a,const node &b) { return a.x<b.x; } inline void pushup(int x) { s[x]=s[lson]+s[rson]; } void updata(int l,int r,int x,int a,int b) { s[x]+=b; if(l==r) return ; int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b); else updata(mid+1,r,rson,a,b); } int query(int l,int r,int x,int a) { if(l==r) return l; int mid=(l+r)>>1; if(s[rson]>=a) return query(mid+1,r,rson,a); return query(l,mid,lson,a-s[rson]); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(),K=rd(); int i,a,b,c; for(i=1;i<=n;i++) { c=rd(),a=rd()+m,b=rd()+m,R=max(R,c); if(a<=b) p[++tot]=node(a,c,1),p[++tot]=node(b,c,-1); else p[++tot]=node(a,c,1),p[++tot]=node(2*m,c,-1),p[++tot]=node(0,c,1),p[++tot]=node(b,c,-1); } sort(p+1,p+tot+1,cmp); for(i=1;i<=tot;i++) { a=query(0,R,1,K),ans+=(ll)a*a*(p[i].x-p[i-1].x); updata(0,R,1,p[i].y,p[i].k); } printf("%lld",ans); return 0; }
时间: 2024-10-20 12:10:58