P4293 [WC2010]能量场

题意

给你 \(n\) 个粒子,每个粒子有两个权值 \(m_i,c_i\) 每个相邻有序对 \((a,b)\) 会产生 \(m_am_b(c_a-c_b)\) 的贡献。现让你处理两个问题:

  1. 找出一个有序对使贡献最大。
  2. 找出一个序列成环后贡献和最大。

思路

我们将贡献转化一下:

\[m_am_b(c_a-c_b)=m_ac_am_b-m_bc_bm_a
\]

那么这就形成了一个叉积的形式。即将每个点 \(i\) 转化为 \(x=m_ic_i,y=m_i\) 的向量。

那么第一问就等价于求叉积最大的两个向量。具体怎么求后面再说。

那么第二问就是将若干个向量依次首尾相接地叉积和。因为所有点都在第一象限,所以这等价于求一个多边形的面积的两倍。(不会的可以自己根据叉积意义推下)

那么我们让贡献和最大,相当于求一个构成多边形面积最大的序列——凸包。于是我们求一下凸包就行了。

至于第一问,我们要快速得到两个点叉积的最大值,发现叉积最大的两个点一定在凸包上。并且发现,顺次遍历所有点并用一个指针记录另一个点的位置,发现叉积的绝对值是单调的。那么我们用类似半平面交的方法扫两遍凸包就行了,即正反各扫一遍(因为边界条件可能错误,但扫两遍一定会统计完全)。

实现

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
namespace star
{
const int maxn=5e4+10;
int n,m=1,ans,Ans[2],q[maxn];
struct vec{
double x,y;
int id;
vec(double x=0,double y=0,int id=0):x(x),y(y),id(id){}
vec operator + (const vec &a) const {return vec(x+a.x,y+a.y);}
vec operator - (const vec &a) const {return vec(x-a.x,y-a.y);}
double operator * (const vec &a) const {return x*a.y-y*a.x;}
bool operator < (const vec &a) const {return x<a.x or (x==a.x and y<a.y);}
}a[maxn];
inline void work(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
double a,b;
scanf("%lf%lf",&a,&b);
star::a[i]=vec(a*b,a,i);
}
sort(a+1,a+1+n);
q[1]=1;
for(int i=2;i<=n;i++){
while(m>1 and (a[q[m]]-a[q[m-1]])*(a[i]-a[q[m]])<=0) m--;
q[++m]=i;
}
int tmp=m;
for(int i=n-1;i;i--){
while(m>tmp and (a[q[m]]-a[q[m-1]])*(a[i]-a[q[m]])<=0) m--;
q[++m]=i;
}
for(int i=1,j=2;i<=m;i++){
while(fabs(a[q[i]]*a[q[j]])<fabs(a[q[i]]*a[q[j+1]])) j=j%(m-1)+1;
double res=a[q[i]]*a[q[j]];
if(ans<fabs(res)){
ans=fabs(res);
if(res>0)Ans[0]=i,Ans[1]=j;
else Ans[0]=j,Ans[1]=i;
}
}
for(int i=m,j=m-1;i;i--){
while(fabs(a[q[i]]*a[q[j]])<fabs(a[q[i]]*a[q[j==1?m-1:j-1]])) j=j==1?m-1:j-1;
double res=a[q[i]]*a[q[j]];
if(ans<fabs(res)){
ans=fabs(res);
if(res>0)Ans[0]=i,Ans[1]=j;
else Ans[0]=j,Ans[1]=i;
}
}
printf("%d %d\n%d\n",a[q[Ans[0]]].id,a[q[Ans[1]]].id,m-1);
for(int i=1;i<m;i++) printf("%d ",a[q[i]].id);
}
}
signed main(){
star::work();
return 0;
}

补充

洛谷的另外一篇题解在代码在数据较小时进行了特判以水过第一个测试点,实际上如果不加特判其根本无法通过此题,原因很可能就是没有进行反方向统计答案。

P4293 [WC2010]能量场的更多相关文章

  1. BZOJ1758: [Wc2010]重建计划

    题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...

  2. 洛谷 P4292 [WC2010]重建计划 解题报告

    P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...

  3. [WC2010]重建计划 长链剖分

    [WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...

  4. 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)

    [BZOJ1758][WC2010]重建计划(点分治,单调队列) 题面 BZOJ 洛谷 Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表 ...

  5. 「WC2010」重建计划(长链剖分/点分治)

    「WC2010」重建计划(长链剖分/点分治) 题目描述 有一棵大小为 \(n\) 的树,给定 \(L, R\) ,要求找到一条长度在 \([L, R]\) 的路径,并且路径上边权的平均值最大 \(1 ...

  6. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

  7. bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

    两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...

  8. bzoj 1758: [Wc2010]重建计划

    Description Input 第 一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案 ...

  9. BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...

随机推荐

  1. 【问题记录】—SignalR连接断线重连

    起因: ASP.NET Core SignalR是一个开源库,可简化向应用添加实时 SignalR Web 功能. 实时 Web 功能使服务器端代码能够立即将内容推送到客户端.(相信大家都用得比较多了 ...

  2. VBS脚本编程(4)——流程控制语句

    分支结构--If .. Then .. Else .. 根据表达式的值有条件地执行一组语句. If condition Then statements [Else elsestatements ] 或 ...

  3. Android系统编程入门系列之清单文件

    在上一篇文章中已经提到,Android系统加载应用程序之后,首先会读取该应用程序的AndroidManifest.xml清单文件,之后根据该清单文件加载后边的东西.所以要开发应用程序,自然要先知道清单 ...

  4. 41.1、shell编程案例

    1.案例1(表达式案例): 开发shell脚本分别实现以定义变量,脚本传参以及read读入的方式比较2个整数大小.用条件表达式(禁if) 进行判断并以屏幕输出的方式提醒用户比较结果: [root@ba ...

  5. js 实时监听滚动条状态 判断滚动条位置

      var scrollFunc = function (e) {    e = e || window.event; var t = document.documentElement.scrollT ...

  6. python之set集合,基础篇

    集合:set 特点:1>.无序 ,因为集合是无序的,所以不可用下标值查询,也不可切片2>.去重 ,一个集合内不能有两个相同的元素3>.可添加,可删除,不可修改等等4>.集合内的 ...

  7. SpringCloud 微服务最佳开发实践

    Maven规范 所有项目必须要有一个统一的parent模块 所有微服务工程都依赖这个parent,parent用于管理依赖版本,maven仓库,jar版本的统一升级维护 在parent下层可以有 co ...

  8. hdu 6092 Rikka with Subset 01背包 思维

    dp[i][j]表示前i个元素,子集和为j的个数.d[i][j] = d[i][j] + d[i-1][j-k] (第i个元素的值为k).这里可以优化成一维数组 比如序列为 1 2 3,每一步的dp值 ...

  9. 整理!企业选择好用的CRM系统的要点(上)

    随着市场经济的发展,对任何行业的企业来说,客户都是非常重要的一个部分.CRM系统帮助企业做到以客户为中心,它可以根据客户的具体要求进行跟进和反馈,在很大程度上提高公司的客户服务水平和客户满意度,进而提 ...

  10. CentOS-Docker安装phpMyAdmin(MySQL的web客户端)

    注:phpMyAdmin是一款MySQL的web客户端,还是很直观且好用的,所以推荐给你~ 下载镜像 $ docker pull phpmyadmin/phpmyadmin 运行镜像 1.无指定固定数 ...