[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 提交提交记录统计讨论测试数据 题目描 ...
随机推荐
- linux--解决anaconda升级pip问题
Anaconda指的是一个开源的Python发行版本,其包含了conda.Python等180多个科学包及其依赖项. 在用pip install命令安装东西时,有时会提示如下错误:升级pip You ...
- 【OCR技术系列之二】文字定位于切割
要做文字识别,第一步要考虑的就是怎么将每一个字符从图片中切割下来,然后才可以送入我们设计好的模型进行字符识别.现在就以下面这张图片为例,说一说最一般的字符切割的步骤是哪些. 当然,我们实际上要识别的图 ...
- Asp.net ------ 开发web 网站
HTML文件变成可以动态界面,经常会变成后缀有: 使用 .NET 开发的展示界面后缀是 .aspx 使用java 开发的展示界面后缀是 .jsp 使用php 开发的展示界面后缀是 .php 本 ...
- Asp.Net Mvc自定义控件之树形结构数据生成表格 - WPF特工队内部资料
最近项目中有一个需求,将树形结构的数据,以表格的形式展示在页面中,下图是最终呈现效果: 源码: @{ Layout = null; } <!DOCTYPE html> <html&g ...
- sql server 查询出整数 (可灵活运用)
系统辅助用表,常用来获取数字,当然还有其他用途
- Linux帮助——常用命令
Linux帮助——常用命令 摘要:本文主要学习了Linux系统中常用的一些命令. uname命令 uname命令可以显示电脑以及操作系统的相关信息. 基本语法 uname [选项] 选项说明 -a:显 ...
- 在执行方法和Web资源中获取传递过来参数的值
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复228或者20161026可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- python从入门到放弃之线程篇
一,什么是多线程? 1.多线程的概念? 说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程. 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分 ...
- MySQL通过SHOW TABLE STATUS查看库中所有表的具体信息
有时候我们想看下指定库下所有表的使用情况,比如,查询表的Table大小,什么时候创建的,数据最近被更新的时间(即最近一笔insert/update/delete的时间).这些信息对我们进行库表维护很有 ...
- 记录一下自己在MVC项目中如何防CSRF攻击,直接上代码
1.前端的处理: 2.后台 1.)添加过滤器,哪里用放哪里 2.)需要验证的方法上直接添加过滤器即可 大功告成 以下为过滤器代码块 /// <summary>/// ajax中加上Anti ...