[LOJ 6213]「美团 CodeM 决赛」radar
[LOJ 6213]「美团 CodeM 决赛」radar
题意
给定 \(n\) 个横坐标 \(x_i\) , 为它们选择一个不超过 \(y_i\) 的纵坐标 \(h_i\), 产生 \(c_ih_i\) 的花费. 选择之后产生的总价值是所有以 \((x_i,h_i)\) 到 \(x\) 轴的垂线段为斜边上的高的等腰直角三角形的并的面积. 最大化总价值与总花费之间的差并输出这个差.
\(n\le 1\times 10^5\).
题解
首先有一个比较显然的沙雕性质, 就是某个三角形的高要么是 \(0\) 要么是 \(y_i\). 因为假设已经选择了一些三角形, 要求选择这个点之后对最后答案的贡献, 必然是一个下凸的二次函数. 显然这样的函数的区间最大值只能取在端点.
其次有另一个显然但是容易被忽略的性质, 就是最优解中不存在一个三角形被另一个三角形完全包含. 也就是说当计算选中一个新的三角形的贡献的时候不可能会出现一些鬼畜边界线的情况考试时成功忽略这个性质于是没敢写
因为不可能被完全包含, 所以我们可以按照三角形在 \(x\) 轴上覆盖的右端点升序排序, 定义 \(dp_i\) 表示前 \(i\) 个三角形中选中最后一个三角形时能产生的最大答案. 因为不难发现唯一需要出现的浮点数是 \(\frac 1 4\), 于是我们计算答案的 \(4\) 倍, 这样就有三种转移情况.
定义 \(l_i,r_i\) 分别为三角形在 \(x\) 轴上覆盖的左右端点, \(w_i\) 为 \(4(y_i^2-c_iy_i)\) :
\begin{cases}
dp_j+w_i &(r_j<l_i)\\
dp_j-(r_j-l_i)^2+w_i &(r_j\ge l_i)
\end{cases}
\]
其中第一种转移显然是个前缀 \(\max\), 因为已经按 \(r_i\) 排过序了所以直接二分找到最后一个做这种贡献的位置然后取前缀 \(\max\) 就可以了.
第二种转移需要拆一拆...
dp_i&=\max_{j<i,r_j\ge l_i} \{dp_j-(r_j-l_i)^2+w_i\}\\
&=\max_{j<i,r_j\ge l_i}\{dp_j-r_j^2+2r_jl_i-l_i^2+w_i\}\\
&=\max_{j<i,r_j\ge l_i}\{dp_j-r_j^2+2r_jl_i\}-l_i^2+w_i
\end{aligned}
\]
其中 \(\max\) 里面是一个一次函数的形式, 可以用李超树来搞.
等一下!
李超树怎么处理 \(r_j\ge l_i\) 这个限制呢? 换句话说, 我们怎么在计算第二部分贡献的时候排除 \(r_j<l_i\) 的点的贡献呢?
其实不用排除因为如果某个点同时做贡献的话第二种贡献是要小于第一种的233
于是直接李超树上就可以了. 总时间复杂度 \(O(n\log n)\).
参考代码
#include <bits/stdc++.h>
const int MAXN=1e5+10;
typedef long long intEx;
struct Point{
int l;
int r;
intEx w;
};
Point P[MAXN];
int n;
int s[MAXN];
intEx smax[MAXN];
struct Line{
intEx k;
intEx b;
Line(const intEx& a,const intEx& b):k(a),b(b){}
inline intEx operator()(const int& x)const{
return k*s[x]+b;
}
};
struct Node{
int l;
int r;
Line f;
Node* lch;
Node* rch;
~Node();
Node(int,int);
intEx Query(int);
void Insert(Line);
};
int main(){
freopen("radar.in","r",stdin);
freopen("radar.out","w",stdout);
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
P[i].l=x-y;
P[i].r=x+y;
s[i]=P[i].l;
P[i].w=4ll*y*y-4ll*c*y;
}
std::sort(P+1,P+n+1,
[](const Point& a,const Point& b){
return a.r<b.r;
}
);
std::sort(s+1,s+n+1);
int cnt=std::unique(s+1,s+n+1)-s-1;
Node* N=new Node(1,cnt);
for(int i=1;i<=n;i++){
// printf("[%d,%d] w=%lld\n",P[i].l,P[i].r,P[i].w);
int h=std::lower_bound(s+1,s+cnt+1,P[i].l)-s;
intEx dp=N->Query(h)-1ll*P[i].l*P[i].l+P[i].w;
int p=std::lower_bound(P+1,P+n+1,P[i].l,
[](const Point& a,const int& b){
return a.r<b;
}
)-P-1;
dp=std::max(smax[p]+P[i].w,dp);
N->Insert(Line(2*P[i].r,dp-1ll*P[i].r*P[i].r));
smax[i]=std::max(smax[i-1],dp);
}
printf("%lld.%02lld\n",smax[n]>>2,(smax[n]&3)*25);
delete N;
}
return 0;
}
intEx Node::Query(int x){
if(this->l==this->r)
return this->f(x);
else{
if(x<=this->lch->r)
return std::max(this->lch->Query(x),this->f(x));
else
return std::max(this->rch->Query(x),this->f(x));
}
}
void Node::Insert(Line f){
int mid=(this->l+this->r)>>1;
if(f(mid)>this->f(mid))
std::swap(f,this->f);
intEx ld=this->f(this->l)-f(this->l);
intEx rd=this->f(this->r)-f(this->r);
if(ld>=0&&rd>=0)
return;
else if(rd>=0)
this->lch->Insert(f);
else
this->rch->Insert(f);
}
Node::~Node(){
if(this->lch)
delete this->lch;
if(this->rch)
delete this->rch;
}
Node::Node(int l,int r):l(l),r(r),f(0,-1e18),lch(NULL),rch(NULL){
if(l!=r){
int mid=(l+r)>>1;
this->lch=new Node(l,mid);
this->rch=new Node(mid+1,r);
}
}

[LOJ 6213]「美团 CodeM 决赛」radar的更多相关文章
- LibreOJ #6212. 「美团 CodeM 决赛」melon
二次联通门 : LibreOJ #6212. 「美团 CodeM 决赛」melon /* LibreOJ #6212. 「美团 CodeM 决赛」melon MDZZ 这是决赛题?? */ #incl ...
- LOJ #6192. 「美团 CodeM 复赛」城市网络 (树上倍增)
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB 时间限制:500 ms 标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接 ...
- LOJ#6085. 「美团 CodeM 资格赛」优惠券(set)
题意 题目链接 Sol 考虑不合法的情况只有两种: 进去了 再次进去 没进去 但是出来了 显然可以用未知记录抵消掉 直接开个set维护一下所有未知记录的位置 最优策略一定是最后一次操作位置的后继 同时 ...
- loj 6085.「美团 CodeM 资格赛」优惠券
题目: 一个有门禁的大楼,初始时里面没有人. 现在有一些人在进出大楼,每个人都有一个唯一的编号.现在有他们进出大楼的记录,但是有些被污染了,只能知道这里有一条记录,具体并不能知道. 一个人只有进大楼, ...
- loj 6084.「美团 CodeM 资格赛」跳格子
题目: link 题解: 尽量走\(a\). 只要保证走\(a\)后到达的点一定可以到终点就可以走. 所以从终点开始\(dfs\)出所有能够到达终点的点. 然后再从起点开始\(dfs\)路径即可. 如 ...
- loj 6083.「美团 CodeM 资格赛」数码
题目: 给定两个整数\(l\)和\(r\),对于任意\(x\),满足\(l\leq x\leq r\),把\(x\)所有约数写下来. 对于每个写下来的数,只保留最高位的那个数码.求\([1,9]\)中 ...
- LiberOJ #6210. 「美团 CodeM 决赛」tree 树形DP
题目链接:点这里 题解: 需要证明,所求的路径一定是全部权值都为1或者,路径上权值至多有一个为2其余为1且权值2在路径中央. 然后树形DP 设定dp[i][0/1] 以1为根的情况下,以i 节点下子树 ...
- loj #6191. 「美团 CodeM 复赛」配对游戏 期望dp
题意:有一个栈,随机插入 $n$ 次 $0$/$1$ 如果栈顶是 $1$,然后插入 $0$,则将这两个元素都弹出,否则,插入栈顶. 求:$n$ 次操作后栈中期望的元素个数. 我们发现,按照上述弹栈方式 ...
- LibreOJ #6192. 「美团 CodeM 复赛」城市网络
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: sqc 提交提交记录统计讨论测试数据 题目描 ...
随机推荐
- P3525 INS-Inspection
这道题的题面有点问题,如果按照题面做,应该是A不了的,下面引用一下评论里@REM_001的翻译 一棵n个节点的树,行动中心S从1->N.从S出发前往任意一个未标记到的点(沿树上两点的唯一路径走) ...
- win10系统使用Telnet命令时提示“telnet不是内部或外部命令”
in10系统使用Telnet命令时提示“telnet不是内部或外部命令”问题的处理方案 win10系统使用的过程中很多用户会遇到使用Telnet命令时提示“telnet不是内部或外部命令”的问题,这样 ...
- Codeforces Round #599 (Div. 1) C. Sum Balance 图论 dp
C. Sum Balance Ujan has a lot of numbers in his boxes. He likes order and balance, so he decided to ...
- Python ASCII码与字符相互转换
ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和 ...
- PHP 高级面试题 - 如果没有 mb 系列函数,如何切割多字节字符串
需求 如果需要将可能含有中文的字符串进行拆分成数组,我们下面以 utf-8 编码为例. 解决方案一 我习惯的方法可能是: mb_internal_encoding("UTF-8") ...
- 瓜子IM智能客服系统的数据架构设计(整理自现场演讲)
本文由ITPub根据封宇在[第十届中国系统架构师大会(SACC2018)]现场演讲内容整理而成. 1.引言 瓜子业务重线下,用户网上看车.预约到店.成交等许多环节都发生在线下.瓜子IM智能客服系统的目 ...
- 用Fastclick解决移动端300ms延迟问题
移动设备上的浏览器默认会在用户点击屏幕大约延迟300毫秒后才会触发点击事件,这是为了检查用户是否在做双击. 为了能够立即响应用户的点击事件,才有了FastClick. 用法: 引入fastclick. ...
- 学习 正则表达式 js java c# python 通用
正则表达式 js java c# python 学习网站 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Globa ...
- laravel中的表单请求类型和CSRF防护(六)
laravel中为我们提供了绑定不同http请求类型的函数. Route::get('/test', function () {}); Route::post('/test', function () ...
- 数据库——数据库设计 E-R图向关系模型的转换
1.将下列物资管理E-R图转换为关系模式: 转换原则 ⒈ 一个实体型转换为一个关系模式.关系的属性:实体型的属性关系的码:实体型的码 ⒉ 一个m:n联系转换为一个关系模式(初步,以后可能调整). ...