您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest - Team 7:1008. Hard challenge(模拟)

2017-08-15 22:00 483 查看
其他题目题解:

2017 Multi-University Training Contest - Team 7:1005. Euler theorem

2017 Multi-University Training Contest - Team 7:1011. Kolakoski

2017
Multi-University Training Contest - Team 7:1003. Color the chessboard

2017 Multi-University Training Contest - Team 7:1002. Build a tree

2017 Multi-University Training Contest - Team 7:1010. Just do it



一开始很少人做这道,估计都被1010卡住了,实际是道水题

题意:坐标系中有n个点,每个点都有它的价值,除此之外任意两点之间都有连线,连线的价值是两个点的价值乘积,现在你可以画一条经过原点的直线,你可以获得这条直线穿过的所有线段的价值和,求最大价值

题解:所有点按斜率排序,注意不是无脑从小到大,因为斜率的变化范围是(0,∞) (-∞,0),所以要稍微处理一下

之后考虑一条与x轴重合的直线,所有在一二象限的点和在x轴正半轴上的点都在直线上面,其他都在直线下面

记录valup为所有上方点的价值和,valdown为所有下方点的价值和,

这样可以O(n)计算这条直线获得的价值(∑val[i]*valdown (i∈up))

然后就可以慢慢的顺时针旋转这条直线,直到翻转180°,中间每经过一个点就说明当前点跑到了直线的另外一边,重新计算一次价值和,最后中间的最大价值就是答案

但这复杂度不是O(n²)的么,遍历O(n),每次计算O(n)

其实不然,因为每次只有一个点发生变化,所以可以O(1)重新计算答案

假设遍历到x点时,x从直线的上端到了直线下端

那么显然有sum -= val[i]*valdown;valdown += val[i];valup -= val[i];sum += valup

这样就只有排序的复杂度了

#include<stdio.h>
#include<algorithm>
using namespace std;
#define LL long long
typedef struct Point
{
double x, y;
double k;
LL t, val;
bool operator < (const Point &b) const
{
if(k>0 && b.k<0)
return 1;
else if(k<0 && b.k>0)
return 0;
else
return k<b.k;
}
}Point;
Point s[50005];
int main(void)
{
LL T, n, i, up, down, now, ans;
scanf("%lld", &T);
while(T--)
{
scanf("%lld", &n);
up = down = 0;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lld", &s[i].x, &s[i].y, &s[i].val);
if(s[i].y>=0)
{
if(s[i].x==0)
s[i].k = 1e9+1000;
else
s[i].k = s[i].y/s[i].x;
if(s[i].y==0 && s[i].x<0)
{
down += s[i].val;
s[i].t = -1;
}
else
{
up += s[i].val;
s[i].t = 1;
}
}
else
{
if(s[i].x==0)
s[i].k = 1e9+1000;
else
s[i].k = s[i].y/s[i].x;
down += s[i].val;
s[i].t = -1;
}
}
now = 0;
for(i=1;i<=n;i++)
{
if(s[i].t==1)
now += s[i].val*down;
}
ans = now;
sort(s+1, s+n+1);
for(i=1;i<=n;i++)
{
if(s[i].t==1)
{
s[i].t = -1;
now -= s[i].val*down;
up -= s[i].val;
down += s[i].val;
now += s[i].val*up;
}
else
{
s[i].t = 1;
now -= s[i].val*up;
up += s[i].val;
down -= s[i].val;
now += s[i].val*down;
}
ans = max(ans, now);
}
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐