zoukankan      html  css  js  c++  java
  • [ABC139F] Engines || [POI2018]Pionek

    题目描述

    给定 (N) 个向量,选出一些向量使得它们的和的模长最大。

    正解

    发现选出来的向量,在极角排序之后一定是一段连续的区间。

    由于数据范围很小,我这里给出的是 (O(n^2)) 做法,但其实还有更加优秀的 (O(n log n)),(复杂度瓶颈在排序上,找区间用 two-pointer )。

    如何用 two-pointer ?

    假如已经知道答案向量的方向,那么对它有贡献的 (180^{circ}) 的半平面的向量都必须选。

    枚举左端点点向量,右端点往右边移动即可。

    (color{DeepSkyBlue} {Code :})

    #include <bits/stdc++.h>
    #define N 105
    
    using namespace std;
    
    int n;
    
    struct vec {
    	long long x, y;
    	vec (long long tx = 0, long long ty = 0) { x = tx, y = ty; }
    	vec operator + (const vec &t) const { return vec(x + t.x, y + t.y); }
    	vec operator - (const vec &t) const { return vec(x - t.x, y - t.y); }
    	long long lenth() { return x * x + y * y; }
    }a[2 * N];
    
    bool cmp(const vec &lhs, const vec &rhs) {
    	return atan2(lhs.y, lhs.x) < atan2(rhs.y, rhs.x);
    }
    
    inline int read() {
    	int x = 0; bool neg = false; char ch = getchar();
    	while(!isdigit(ch)) (ch == '-') && (neg = true), ch = getchar();
    	while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    	return neg ? -x : x;
    }
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; ++i)
    		a[i].x = read(), a[i].y = read();
    	
    	sort(a + 1, a + n + 1, cmp);
    	
    	for(int i = 1; i <= n; ++i)
    		a[n + i] = a[i];
    	
    	vec cur;
    	long long ans = 0;
    	for(int l = 1; l <= n; ++l) {
    		cur = vec(0, 0);
    		for(int r = l; r < l + n; ++r) {
    			cur = cur + a[r];
    			ans = max(ans, cur.lenth());
    		}
    	}
    	
    	printf("%.10lf
    ", sqrt(ans));
    	return 0;
    }
    
  • 相关阅读:
    CORS跨域资源共享漏洞
    Linux Restricted Shell Bypass
    无情一点并没有错
    [机器学习]numpy broadcast shape 机制
    Chrome和IE的xss过滤器分析总结
    php使用substr中文乱码问题
    mac下自定义伪协议配置
    【转】前端黑魔法之远程控制地址栏
    Windows可信任路径代码执行漏洞
    小记一次mysql启动失败没有日志的处理
  • 原文地址:https://www.cnblogs.com/Lskkkno1/p/12559701.html
Copyright © 2011-2022 走看看