【题目描述】:
给定N个同心的扇形,求有多少面积,被至少K个扇形所覆盖。
【题目解法】:
转化以下模型变成:
给你n个矩形,矩形的下端贴着x轴,询问有多少的面积至少被k个矩形覆盖
对矩形的竖边扫描线,然后维护一个线段树,每次询问第k大的数字
注意这里矩形的面积定义为a*h^2,a为底边长,h为高
复杂度O(N log N)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100005;
const int M=500005;
struct node {int t;} tree[N*4];
struct Node
{
int pos,h,flag;
inline bool operator < (const Node &a) const
{
if (pos==a.pos) return flag<a.flag;
return pos<a.pos;
}
} a[M];
int n,m,limit,tot; long long ans;
inline long long getint()
{
long long x=0; char c=getchar(); bool flag=false;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') flag=true,c=getchar();
while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
if (flag) return -x; else return x;
}
void init()
{
n=getint(); m=getint(); limit=getint(); tot=0; int nowm=0;
for (int i=1; i<=n; i++)
{
int h=getint(),l=getint(),r=getint(); nowm=max(nowm,h);
if (l<=r)
{
++tot; a[tot].pos=l; a[tot].flag=1; a[tot].h=h;
++tot; a[tot].pos=r; a[tot].flag=-1; a[tot].h=h;
}
if (l>r)
{
++tot; a[tot].pos=-m; a[tot].flag=1; a[tot].h=h;
++tot; a[tot].pos=r; a[tot].flag=-1; a[tot].h=h;
++tot; a[tot].pos=l; a[tot].flag=1; a[tot].h=h;
++tot; a[tot].pos=m; a[tot].flag=-1; a[tot].h=h;
}
}
sort(a+1,a+tot+1); m=nowm;
}
void modify(int p,int l,int r,int x,int y)
{
if (l==r) {tree[p].t+=y; return;} int mid=(l+r)/2;
if (x<=mid) modify(p*2,l,mid,x,y); else modify(p*2+1,mid+1,r,x,y);
tree[p].t=tree[p*2].t+tree[p*2+1].t;
}
int ask(int p,int l,int r,int x)
{
if (l==r) return (tree[p].t<x)?0:l; int mid=(l+r)/2,son=tree[p*2+1].t;
if (x<=son) return ask(p*2+1,mid+1,r,x); else return ask(p*2,l,mid,x-son);
}
void solve()
{
int last=0;
for (int i=1,j=1; i<=tot; i=j)
{
int now=ask(1,1,m,limit); ans=ans+(long long)now*now*(a[i].pos-last);
for (;(j<=tot)&&(a[j].pos==a[i].pos);j++) modify(1,1,m,a[j].h,a[j].flag);
last=a[i].pos;
}
printf("%lld\n",ans);
}
int main()
{
init();
solve();
return 0;
}