题解报告——扇形面积并

题目传送门

题目描述

给定 n 个同心的扇形,求有多少面积,被至少k 个扇形所覆盖。

输入输出格式

输入格式:

第一行是三个整数 n,m,k。n 代表同心扇形个数,m代表将(−π ,π ]的角度

区间平均分成2m 份。

从第二行开始的 n 行,每行三个整数r,a1,a2。描述了一个圆心在原点的

扇形,半径为r,圆心角是从弧度

π∗a1/mπ*a1/mπa1/m到π∗a2/mπ*a2/mπa2/m(a1 不一定小于 a2)。

输出格式:

输出一个整数 ans ,π/2m∗ansπ/2m*ansπ/2mans等于至少k 个扇形所覆盖的总面积。

数据保证答案在263−12^{63} - 12631范围内。

输入输出样例

输入样例#1: 复制
3 8 2
1 -8 8
3 -7 3
5 -5 5
输出样例#1: 复制
76
输入样例#2: 复制
2 4 1
4 -4 2
1 -4 4
输出样例#2: 复制
98

说明

1≤n≤10^5, 1≤m≤10^6,1≤k≤5000,1≤ri≤10^5,-m≤a1,a2≤m


【思路分析】

第一眼看到这个题以为是计算几何,一看通过数也不多,又是一道算几毒瘤题。。。但是我们仔细看看,发现数据都是整数,并且良心出题人将输出数据都为你做成了整数,感觉似乎就不像毒瘤算几了??!!再观察发现将圆划分成了相等的几块小区间,顿时感觉这道题变更成了区间问题了,我们尝试用线段树搞一搞??!!

对于查询被至少k个扇形覆盖的区间,等同于查询当前区间覆盖了扇形的第k大半径,既然有k的存在,那么数据结构无非就是平衡树和权值线段树,发现区间很多,平衡树不方便维护区间与区间之间的关系,那么我们考虑用权值线段树,区间k大问题??主席树板题??!!,其实不然,我们并不需要用主席树,只用开一棵权值线段树即可。

我们将扇形按起点排序,发现这就有点类似于扫描线,有下边界,有上边界,差分维护扇形起点终点即可。

然而我们发现这道题是有环的,即一个扇形的可能跨过我们的起点(而矩形面积并则不会),我们只需要将这样的扇形拆分成两块维护即可。。。AC了??!!

这次就真的应该可以A了!!!


【代码实现】

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 typedef long long ll;
 8 void read(int &x)
 9 {
10     int f;char ch;
11     while(!isdigit(ch=getchar())&&ch!='-'); ch=='-'?(f=-1,x=0):(f=1,x=ch-'0');
12     while(isdigit(ch=getchar())) x=x*10+ch-'0';x=x*f;
13 }
14 const int N=1e5+5,M=1e6+5;
15 struct sd{
16     int son[2],num;
17 }t[N<<1];
18 int n,m,k,cnt,root,mx;
19 vector<int> cf[M<<1];
20 void insert(int &v,int l,int r,int pos,int add)
21 {
22     if(!v) v=++cnt;t[v].num+=add;
23     if(l==r) return;
24     int mid=l+r>>1;
25     if(pos<=mid) insert(t[v].son[0],l,mid,pos,add);
26     else insert(t[v].son[1],mid+1,r,pos,add);
27 }
28 int ask(int v,int l,int r,int k)
29 {
30     if(l==r) return l;
31     int mid=l+r>>1,ls=t[v].son[0],rs=t[v].son[1];
32     if(t[ls].num>=k) return ask(ls,l,mid,k);
33     else return ask(rs,mid+1,r,k-t[ls].num);
34 }
35 ll mul(ll a){return a*a;}
36 int main()
37 {
38     int l,r,ri;
39     read(n),read(m),read(k);
40     for(int i=1;i<=n;i++){
41         read(ri),read(l),read(r);
42         l+=m+1,r+=m;
43         if(l==2*m+1) l=1;if(r==2*m) r=-1;
44         if(r==-1) cf[l].push_back(ri);
45         else if(l>r) cf[l].push_back(ri),cf[1].push_back(ri),cf[r+1].push_back(-ri);
46         else cf[l].push_back(ri),cf[r+1].push_back(-ri);
47         mx=max(ri,mx);
48     }
49     ll ans=0;
50     for(int i=1;i<=2*m;i++)
51     {
52         int ss=cf[i].size();
53         for(int j=0;j<ss;j++)
54         if(cf[i][j]>0){
55             int gg=cf[i][j];
56             insert(root,1,mx,cf[i][j],1);
57         }
58         else insert(root,1,mx,-cf[i][j],-1);
59         if(t[root].num>=k) ans=ans+mul(1ll*ask(root,1,mx,t[root].num-k+1));
60     }
61     printf("%lld",ans);
62     return 0;
63 }

猜你喜欢

转载自www.cnblogs.com/genius777/p/9693669.html