其实不算太难,这场应该是有可能可以 AK 的
Part1. 题面
平面直角坐标系上有 $n$ 个点,第 $i$ 个点坐标为 $(x_i,y_i)$、权值为 $v_i$。
你需要在直线 $y=x$ 上选择两个点 $(a,a),(b,b)$($a\le b$),并且以 $(a,a)$ 为左下角、$(b,b)$ 为右上角作一个正方形。得分为在这个正方形中的点的权值之和(在正方形的边上也算)减去正方形的边长(不是周长)。
求怎样选择 $a,b$ 可以使得得分最大,求最大得分以及此时的 $a,b$(任意一个)。
数据规模
- $1\le n\le 5\times10^5$;
- $0\le x_i,y_i\le 10^9$;
- $-10^6\le v_i\le10^6$;
- 要求输出的 $0\le a,b\le2\times10^9$;
Part2. 解析
扫描线的思想是把点转成能够框住它的矩形;这道题也不例外,只是转换有点奇怪。
如果点 $i$ 被正方形框住,就说明 $a\le x_i\le b$ 并且 $a\le y_i\le b$;换种写法 $a\le\min\{x_i,y_i\}\le\max\{x_i,y_i\}\le b$。
发现“能够框住点的矩形”变成了“能够框住一条线段的线段”:也就是线段 $(a,b)$ 要能够把 $(\min\{x_i,y_i\},\max\{x_i,y_i\})$ 框住。于是就变成了一维的 扫描线 ——
显然最优答案要么是什么点都不圈、框一个边长为 0 $(a=b)$ 的正方形;要么是至少有一个点在正方形的边上(否则就可以缩小正方形的边长,使得它仍然圈住已有的点,这样答案一定更优)。所以我们读入时把点 $(x_i,y_i)$ 转成 线段 $(\min\{x_i,y_i\},\max\{x_i,y_i\})$ ,然后把线段的两端点离散化一下。
所以现在就是要确定一条线段 $(a,b)$。从左到右枚举线段的右端点 $b$,那么右端点不超过 $b$ 的线段就有可能被框入 $(a,b)$ 中。我们用线段树维护:当右端点固定为 $b$ 时,左端点选在 $0$ 到 $b$ 的最大答案。所以我们可以这样实现线段树:
- 单点修改:如果线段 $(x,y)$ 的右端点不超过 $b$,就在线段树的 $x$ 处加上该线段的权值 $v$;
- 区间查询:查询在区间 $(0,b)$ 中选择一个点 $a$,线段树中 $(a,b)$ 的所有权值之和 加 $a$ 的最大值;这样求出的最大值再减去 $b$ 就可以得到答案了。当然还要维护选的是哪个点。
Part3. 源代码
1 | /*Lucky_Glass*/ |
The End
Thanks for reading!
Email: lucky_glass@foxmail.com,欢迎提问~