「NOIP 模拟赛 20230706」偷 WiFi
summarization
有一个长度为 的序列 ,将其中若干个数标记。对于序列中的每一个位置 ,其贡献为其左边与右边离它最近的被标记的数的数值的和。求出最大的贡献总和。()
solution
首先显然, 一定要标记。然后考虑分别求相邻的标记数之间的贡献。
设 为相邻的两个标记数的位置。对于 区间: 区间的贡献为 , 位置右边的贡献为 , 位置左边的贡献为 ,所以总和为 。
发现 是梯形面积公式的一半,所以如果我们将每一个 放入坐标系,那么贡献总和则等于如图阴影部分的面积的两倍:(红色的点为标记数所代表的点)
那么问题就变为选取若干个点,使其围成的梯形面积最大,显然选取上凸壳中的点即可。
时间复杂度
code
CI N = 2e6; ll n, p[N + 5], top = 0; struct node {ll x; ll y;} sk[N + 5];
ll cross (node a, node b, node c) {return (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);}
int main () {
RI i, j; for (Read (n), i = 1; i <= n; ++ i) Read (p[i]);
for (i = 1; i <= n; ++ i) {
node now = {i, p[i]}; W (top >= 2 && cross (sk[top - 1], sk[top], now) >= 0) -- top; sk[++ top] = now;
} ll ans = 0; for (i = 1; i < top; ++ i) ans += (sk[i].y + sk[i + 1].y) * (sk[i + 1].x - sk[i].x);
printf ("%lld\n", ans);
return 0;
}
分类:
OI
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探