2017 Multi-University Training Contest

来源:互联网 发布:旅游数据分析报告 编辑:程序博客网 时间:2024/05/21 11:17

其他题目题解:

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 longtypedef 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;elsereturn 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;elses[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;elses[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;}