[Luogu3997] [SHOI2013] 扇形面积并 [线段树][差分]

Link
Luogu - https://www.luogu.org/problemnew/show/P3997
BZOJ - https://www.lydsy.com/JudgeOnline/problem.php?id=4418


假如你也听说校门外的树
容易考虑利用差分前缀和
……但是这道题扇形半径不定
怎么办?


我们依然可以知道哪些角度区间被不少于 k k k 个扇形覆盖
然后每个这样的角度如果被 x x x 个扇形覆盖
那么这个角度产生贡献的半径是覆盖它的扇形里面半径第 x − k + 1 x-k+1 xk+1 小那个扇形的半径
产生的贡献是这个半径的平方
来一发扫描线就完事了


你也可以考虑直接覆盖,不过 Lazytag 不好做,复杂度貌似有点假(?)
注意题目说得很不清楚…… a 1 > a 2 a_1>a_2 a1>a2 的时候这个扇形过角度 π \pi π

我好菜啊
人傻BUG多


#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
//#define _Rep(i,j,k) for(register int i=(j);i<=(k);++i)
const int MAXN = 2e5+5;
const int MAXM = 2e6+5;
const int MAXR = 1e5;
const int MAXS = (MAXR<<2)+5;
int n, m, M, k, tot;
#define PII pair<int, int>
PII Mark[MAXM];
int Seg[MAXS], Siz[MAXS];
long long Ans;
//int X[MAXN], L[MAXN], R[MAXN], Id[MAXN];
//inline bool cmp(const int& a, const int& b)
//{
//	return (X[a]==X[b])?((L[a]==L[b])?(R[a]>R[b]):(L[a]>L[b])):(X[a]>X[b]);
//}
void Insert(const int& Pos, const int& L, const int& R, const int& Val, const bool& ar)
{
	Siz[Pos]+=ar?1:-1;
	if (L == R) return;
	int Mid = L + R >> 1;
	if (Val <= Mid) Insert(Pos << 1, L, Mid, Val, ar);
	else Insert(Pos<<1|1, Mid + 1, R, Val, ar);
}
inline int defabs(const int& x)
{
	return (x<0)?(-x):x;
}
inline long long PWO(const int& x)
{
	return 1ll * x * x;
}
inline int Query(const int& Pos, const int& L, const int& R, const int& kth)
{
	if(L==R) return L;
	int Mid = L + R >> 1;
	if(Siz[Pos<<1|1]<kth) return Query(Pos<<1, L, Mid, kth-Siz[Pos<<1|1]);
	else return Query(Pos<<1|1, Mid + 1, R, kth);
}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	M = m << 1;
	for (register int x, l, r, i = 1; i <= n; ++i)
	{
//		++tot;
//		scanf("%d%d%d", &X[tot], &L[tot], &R[tot]);
//		L[tot] += m, R[tot] += m - 1;
//		if (L[tot]>R[tot])
//		{
//			R[tot+1]=R[tot],L[tot+1]=0;
//			R[tot++]=M;
//		}
		scanf("%d%d%d", &x, &l, &r);
		l += m; r += m - 1;
		if(r==M)r=0;
		if(l<=r)Mark[++tot]=make_pair(l,x),Mark[++tot]=make_pair(r+1,-x);
		else Mark[++tot]=make_pair(l,x),Mark[++tot]=make_pair(M,-x),Mark[++tot]=make_pair(0,x),Mark[++tot]=make_pair(r+1,-x);
	}
	sort(Mark+1,Mark+tot+1);
//	_Rep(i, 1, tot) Id[i]=i;
//	sort(Id+1,Id+1+tot,cmp);
	for (register int MarkPos = 1, i = 0; i <= M; ++i)
	{
		while(Mark[MarkPos].first<i && MarkPos <= tot)++MarkPos;
		while(Mark[MarkPos].first==i && MarkPos <= tot)
		{
			Insert(1, 0, MAXR+1, defabs(Mark[MarkPos].second), Mark[MarkPos].second>0);
			++MarkPos;
		}
		Ans += PWO(Query(1, 0, MAXR+1, k));
	}
	printf("%lld", Ans);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值