Solution -「多校联训」最大面积
\(\mathcal{Description}\)
Link.
平面上有 \(n\) 个点 \(A_{1..n}\),\(q\) 次询问,每次给出点 \(P\),求
\]
\(n\le10^5\),\(q\le10^6\)。
\(\mathcal{Solution}\)
初步转化一下式子:
\sum_{i=l}^r\vec{OP}\times\vec{OA_i}&=\sum_{i=l}^r(x_Py_{A_i}-y_Px_{A_i})\\
&=x_P\left(\sum_{i=l}^ry_{A_i}-\frac{y_P}{x_P}\sum_{i=l}^rx_{A_i}\right)~~~~(x_P\not=0)
\end{aligned}
\]
对于 \(x_P=0\) 即求 \(x_{A_{1..n}}\) 的最大子段和;对于 \(x_P\not=0\),提出 \(x_P\) 后,记 \(k=\frac{y_P}{x_P}\),\(y(l,r)=\sum_{i=l}^ry_{A_i}\),\(x(l,r)=\sum_{i=l}^rx_{A_i}\),原式可以看作
\]
并要求最大化 \(x_Pb\)。相当于过某个 \((x(l,r),y(l,r))\) 作斜率为 \(k\) 的直线,求其最大或最小纵截距。若能求出所有 \((x(l,r),y(l,r))\) 构成的凸包,就能在凸壳上二分求解了。
考虑求凸包的方法:分治,对于分支区间 \([l,r]\) 与其中点 \(p\),计算 \((x(l..p,p+1..r),y(l..p,p+1..r))\) 的贡献。分别求出后缀与前缀凸包,根据定义,求出左右凸包的 Minkowski 和即为当前层贡献,加入总点集,最后再求总点集的凸包即可。
复杂度 \(\mathcal O(n\log^2n+q\log n)\)。
\(\mathcal{Code}\)
/* Rainybunny */
#include <cstdio>
#include <vector>
#include <algorithm>
#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
typedef long long LL;
typedef long double LD;
inline int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
}
template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
}
inline LL lmax( const LL a, const LL b ) { return a < b ? b : a; }
namespace PGP {
const LD EPS = 1e-9;
inline int dcmp( const LD a ) {
return -EPS < a && a < EPS ? 0 : a < 0 ? -1 : 1;
}
struct Point {
LL x, y;
Point(): x( 0 ), y( 0 ) {}
Point( const LL a, const LL b ): x( a ), y( b ) {}
inline Point operator + ( const Point& p ) const {
return { x + p.x, y + p.y };
}
inline Point operator - ( const Point& p ) const {
return { x - p.x, y - p.y };
}
inline int operator ^ ( const Point& p ) const {
return dcmp( LD( x ) * p.y - LD( y ) * p.x );
}
inline bool operator < ( const Point& p ) const {
return x != p.x ? x < p.x : y < p.y;
}
inline bool operator == ( const Point& p ) const {
return x == p.x && y == p.y;
}
};
typedef Point Vector;
typedef std::vector<Point> Convex;
inline Convex getConvex( std::vector<Point> vec ) {
static Convex ret; ret.clear();
std::sort( vec.begin(), vec.end() );
vec.resize( std::unique( vec.begin(), vec.end() ) - vec.begin() );
int n = int( vec.size() ), top = 0;
ret.resize( n << 1 );
rep ( i, 0, n - 1 ) {
for ( ; top > 1; --top ) {
if ( ( ( ret[top - 1] - ret[top - 2] )
^ ( vec[i] - ret[top - 2] ) ) > 0 ) break;
}
ret[top++] = vec[i];
}
for ( int tmp = top, i = n - 2; ~i; --i ) {
for ( ; top > tmp; --top ) {
if ( ( ( ret[top - 1] - ret[top - 2] )
^ ( vec[i] - ret[top - 2] ) ) > 0 ) break;
}
ret[top++] = vec[i];
}
top -= n > 1;
return ret.resize( top ), ret;
}
inline int findPole( const Convex& cvx ) {
int ret = -1, n = int( cvx.size() );
rep ( i, 0, n - 1 ) {
if ( !~ret || cvx[ret].y > cvx[i].y
|| ( cvx[ret].y == cvx[i].y && cvx[ret].x > cvx[i].x ) ) {
ret = i;
}
}
return ret;
}
inline void poleSort( Convex& cvx ) {
int pid = findPole( cvx ), n = int( cvx.size() );
pid = n - pid - 1;
std::reverse( cvx.begin(), cvx.end() );
std::reverse( cvx.begin(), cvx.begin() + pid + 1 );
std::reverse( cvx.begin() + pid + 1, cvx.end() );
}
inline Convex minkowskiSum( Convex A, Convex B ) {
static Convex ret; ret.clear();
poleSort( A ), poleSort( B );
int n = int( A.size() ), m = int( B.size() );
Point ap( A[0] ), bp( B[0] );
ret.push_back( ap + bp );
rep ( i, 0, n - 2 ) A[i] = A[i + 1] - A[i];
A[n - 1] = ap - A[n - 1];
rep ( i, 0, m - 2 ) B[i] = B[i + 1] - B[i];
B[m - 1] = bp - B[m - 1];
int i = 0, j = 0;
while ( i < n && j < m ) {
// 注意这里能 hack,应该计算极角来比较,否则无法正确处理共线向量。
ret.push_back( ret.back()
+ ( ( A[i] ^ B[j] ) > 0 ? A[i++] : B[j++] ) );
}
while ( i < n ) ret.push_back( ret.back() + A[i++] );
while ( j < m ) ret.push_back( ret.back() + B[j++] );
return ret;
}
} using namespace PGP;
const int MAXN = 1e5;
int n, q, rpos;
Point A[MAXN + 5];
Convex cvxA;
LL mnsec, mxsec;
inline void buildConvex( const int l, const int r ) {
if ( l == r ) return cvxA.push_back( A[l] );
int mid = l + r >> 1;
buildConvex( l, mid ), buildConvex( mid + 1, r );
static Convex cvxL, cvxR; cvxL.clear(), cvxR.clear();
Point cur;
per ( i, mid, l ) cvxL.push_back( cur = cur + A[i] );
cur = Point();
rep ( i, mid + 1, r ) cvxR.push_back( cur = cur + A[i] );
cvxL = minkowskiSum( getConvex( cvxL ), getConvex( cvxR ) );
for ( const auto& p: cvxL ) cvxA.push_back( p );
}
inline void init() {
buildConvex( 1, n ), cvxA = getConvex( cvxA );
#ifdef RYBY
puts( "+++ cvxA +++" );
for ( auto p: cvxA ) printf( "%lld %lld\n", p.x, p.y );
puts( "--- cvxA ---" );
#endif
if ( cvxA.size() == 1 ) rpos = 0;
else {
rpos = -1;
rep ( i, 1, cvxA.size() - 1 ) {
if ( cvxA[i].x <= cvxA[i - 1].x ) {
rpos = i - 1; break;
}
}
if ( !~rpos ) rpos = cvxA.size() - 1;
}
LL las = 0;
rep ( i, 1, n ) {
if ( ( las += A[i].x ) > mxsec ) mxsec = las;
if ( las < 0 ) las = 0;
}
las = 0;
rep ( i, 1, n ) {
if ( ( las += A[i].x ) < mnsec ) mnsec = las;
if ( las > 0 ) las = 0;
}
}
inline LL solve( const Point& P ) {
if ( !P.x ) return P.y > 0 ? -P.y * mnsec : -P.y * mxsec;
if ( cvxA.size() == 1 ) return P ^ cvxA[0];
Vector kp( P.x, P.y );
if ( kp.x < 0 ) kp.x = -kp.x, kp.y = -kp.y;
int s = int( cvxA.size() );
if ( P.x > 0 ) { // up convex.
int l = rpos, r = s;
while ( l < r ) {
int mid = l + r >> 1;
if ( ( ( cvxA[mid] - cvxA[( mid + 1 ) % s] ) ^ kp ) > 0 )
l = mid + 1;
else r = mid;
}
l %= s;
return P.x * cvxA[l].y - P.y * cvxA[l].x;
} else { // down convex.
int l = 0, r = rpos;
while ( l < r ) {
int mid = l + r >> 1;
if ( ( ( cvxA[( mid + 1 ) % s] - cvxA[mid] ) ^ kp ) > 0 )
l = mid + 1;
else r = mid;
}
l %= s;
return P.x * cvxA[l].y - P.y * cvxA[l].x;
}
}
int main() {
freopen( "area.in", "r", stdin );
freopen( "area.out", "w", stdout );
n = rint(), q = rint();
rep ( i, 1, n ) A[i].x = rint(), A[i].y = rint();
init();
for ( Point P; q--; ) {
P.x = rint(), P.y = rint();
wint( lmax( solve( P ), 0 ) ), putchar( '\n' );
}
return 0;
}
Solution -「多校联训」最大面积的更多相关文章
- Solution -「多校联训」排水系统
\(\mathcal{Description}\) Link. 在 NOIP 2020 A 的基础上,每条边赋权值 \(a_i\),随机恰好一条边断掉,第 \(i\) 条段的概率正比于 \(a ...
- Solution -「多校联训」I Love Random
\(\mathcal{Description}\) 给定排列 \(\{p_n\}\),可以在其上进行若干次操作,每次选取 \([l,r]\),把其中所有元素变为原区间最小值,求能够得到的所有不同序 ...
- Solution -「多校联训」签到题
\(\mathcal{Description}\) Link. 给定二分图 \(G=(X\cup Y,E)\),求对于边的一个染色 \(f:E\rightarrow\{1,2,\dots,c\ ...
- Solution -「多校联训」朝鲜时蔬
\(\mathcal{Description}\) Link. 破案了,朝鲜时蔬 = 超现实树!(指写得像那什么一样的题面. 对于整数集 \(X\),定义其 好子集 为满足 \(Y\sub ...
- Solution -「多校联训」消失的运算符
\(\mathcal{Description}\) Link. 给定长度为 \(n\) 的合法表达式序列 \(s\),其中数字仅有一位正数,运算符仅有 - 作为占位.求将其中恰好 \(k\) ...
- Solution -「多校联训」假人
\(\mathcal{Description}\) Link. 一种物品有 长度 和 权值 两种属性,现给定 \(n\) 组物品,第 \(i\) 组有 \(k_i\) 个,分别为 \((1,a ...
- Solution -「多校联训」古老的序列问题
\(\mathcal{Description}\) Link. 给定序列 \(\{a_n\}\),和 \(q\) 次形如 \([L,R]\) 的询问,每次回答 \[\sum_{[l,r]\su ...
- Solution -「多校联训」Sample
\(\mathcal{Description}\) Link (稍作简化:)对于变量 \(p_{1..n}\),满足 \(p_i\in[0,1],~\sum p_i=1\) 时,求 \(\ma ...
- Solution -「多校联训」光影交错
\(\mathcal{Description}\) Link. 一个游戏包含若干次卡牌抽取,每次以 \(p_l\) 的概率得到 \(+1\),\(p_d\) 的概率得到 \(-1\),否则得到 ...
随机推荐
- vue3.0+ts+setup语法糖props写法
写法一 import defaultImg from '@/assets/images/defaultImg.png' const props = defineProps({ src: { type: ...
- Ubuntu 桌面版使用总结
最近拿出了大学时买的性(游)能(戏)本(机),其实从直观来看,硬件基础还是不错的,但是跑 WIN10, 清了各种广告,关了各种无效进城之后,用起来仍然还是很不爽.可能是已经用惯 mac 了吧,mac给 ...
- flume安装及使用
最近在学习hadoop大数据平台,但是却感觉无从下手,于是看了一些专业的书籍,觉得还是先从下往上为学习也就是从源数据--数据抽取--存储--计算--展示这个路线来学习比较容易一些,所以就先从非结构化数 ...
- CUDA 入门(转)
CUDA(Compute Unified Device Architecture)的中文全称为计算统一设备架构.做图像视觉领域的同学多多少少都会接触到CUDA,毕竟要做性能速度优化,CUDA是个很重要 ...
- 【刷题-LeetCode】123 Best Time to Buy and Sell Stock III
Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...
- setcontext+orw
setcontext+orw 大致可以把2.27,2.29做为两个分界点. 我们先来讨论 2.27 及以下的 setcontext + orw 的写法. 首先 setcontext 是什么?了解过 S ...
- python3调用js的库之execjs
执行JS的类库:execjs,PyV8,selenium,node execjs是一个比较好用且容易上手的类库(支持py2,与py3),支持 JS runtime. 1.安装: pip install ...
- django入门 01 创建项目
安装django库 pip install django 创建--by 终端 django-admin startproject myproject 通过命令创建的django项目,默认不含templ ...
- 布客·ApacheCN 编程/大数据/数据科学/人工智能学习资源 2020.2
特约赞助商 公告 我们愿意普及区块链技术,但前提是互利互惠.我们有大量技术类学习资源,也有大量的人需要这些资源.如果能借助区块链技术存储和分发,我们就能将它们普及给我们的受众. 我们正在招募项目负责人 ...
- 实现Nginx代理WSS协议
因为线上H5游戏需要加上SSL,不想在原来的Web 服务器和游戏服务器支持SSL,只希望 在Nginx代理集群支持SSL.整体架构如下: 从上图可以看出需要总共涉及到https/http 和wss/w ...