[POI2018]Pionek

[POI2018]Pionek

题目大意:

在无限大的二维平面的原点放置着一个棋子。你有\(n(n\le2\times10^5)\)条可用的移动指令,每条指令可以用一个二维整数向量表示。请你选取若干条指令,使得经过这些操作后,棋子离原点的距离最大。

思路:

将所有向量极角排序,然后你选取的向量一定是里面连续的一段,由于所有向量排成一个环,所以要复制一遍接在后面,最后用尺取法枚举左右端点即可。

时间复杂度\(\mathcal O(n\log n)\)。

源代码:

#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
    register char ch;
    register bool neg=false;
    while(!isdigit(ch=getchar())) neg|=ch=='-';
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return neg?-x:x;
}
typedef long long int64;
const int N=4e5+2;
struct Point {
    int64 x,y;
    double a;
    bool operator < (const Point &rhs) const {
        return a<rhs.a;
    }
    Point operator + (const Point &rhs) const {
        return (Point){x+rhs.x,y+rhs.y,a+rhs.a};
    }
};
Point p[N],sum[N];
inline int64 sqr(const int64 &x) {
    return x*x;
}
int main() {
    const int n=getint();
    for(register int i=1;i<=n;i++) {
        p[i].x=getint();
        p[i].y=getint();
        p[i].a=atan2(p[i].x,p[i].y);
    }
    std::sort(&p[1],&p[n]+1);
    std::copy(&p[1],&p[n]+1,&p[n+1]);
    for(register int i=n+1;i<=n*2;i++) {
        p[i].a+=M_PI*2;
    }
    int64 ans=0;
    sum[n*2].a=1e8;
    for(register int i=1,j=1;j<=n*2;j++) {
        sum[j]=sum[j-1]+p[j];
        for(;i<=j&&p[j+1].a-p[i].a>=M_PI;i++) {
            ans=std::max(ans,sqr(sum[j].x-sum[i-1].x)+sqr(sum[j].y-sum[i-1].y));
        }
        if(i<=j) ans=std::max(ans,sqr(sum[j].x-sum[i-1].x)+sqr(sum[j].y-sum[i-1].y));
    }
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/skylee03/p/9725127.html

时间: 2024-08-01 17:26:30

[POI2018]Pionek的相关文章

【BZOJ5099】[POI2018]Pionek 几何+双指针

[BZOJ5099][POI2018]Pionek Description 在无限大的二维平面的原点(0,0)放置着一个棋子.你有n条可用的移动指令,每条指令可以用一个二维整数向量表示.每条指令最多只能执行一次,但你可以随意更改它们的执行顺序.棋子可以重复经过同一个点,两条指令的方向向量也可能相同.你的目标是让棋子最终离原点的欧几里得距离最远,请问这个最远距离是多少? Input 第一行包含一个正整数n(n<=200000),表示指令条数. 接下来n行,每行两个整数x,y(|x|,|y|<=1

[武汉加油] bzoj 5099: [POI2018]Pionek 几何+双指针

几何+双指针 题目大意:现在有 \(n\) 个向量,请你选出来一些向量使它们的和的长度最大,输出最大值的平方. 假如我们已经知道了最终向量的方向,我们要想使长度最大,就需要将所有投影在最终向量正方向上的向量都加起来. 所以我们可以按角度枚举最终向量的方向,我们需要加起来的就是一段移动的区间,我们可以用双指针来维护加起来的向量. 因为最终向量的方向有可能是给出的向量,也有可能是向量之间间隔的方向,所以每次移动指针的时候都要更新一下答案. 因为开始给出的向量不一定有序,所以我们需要先将向量排序. #

【BZOJ5101】[POI2018]Pow&#243;d 并查集

[BZOJ5101][POI2018]Powód Description 在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无穷大的墙,因此水不可能漏到外面.已知水箱内每个格子的高度都是[0,H]之间的整数,请统计有多少可能的水位情况.因为答案可能很大,请对10^9+7取模输出.两个情况不同当且仅当存在至少一个方格的水位在两个情况中不同. Input 第一行包含三个正整数n,m,H(n*m<=500000,1<=H<

【BZOJ5100】[POI2018]Plan metra 构造

[BZOJ5100][POI2018]Plan metra Description 有一棵n个点的无根树,每条边有一个正整数权值,表示长度,定义两点距离为在树上的最短路径的长度. 已知2到n-1每个点在树上与1和n的距离,请根据这些信息还原出这棵树. Input 第一行包含一个正整数n(2<=n<=500000),表示点数. 第二行包含n-2个正整数d(1,2),d(1,3),...,d(1,n-1),分别表示每个点到1的距离. 第三行包含n-2个正整数d(n,2),d(n,3),...,d(

BZOJ5103 : [POI2018]R&#243;znorodno

从上到下枚举上下底边,那么涉及两行的添加和删除. 首先预处理出对于每一列,每个位置添加和删除时,是否会对往下$k$个里出现这个颜色造成影响. 然后对于每种颜色维护一个长度为$m$的bitset,表示哪些列出现过该颜色. 那么每次修改时,找到前驱和后继,对这一行答案的影响是一段区间加,差分前缀和即可. 时间复杂度$O(\frac{nm^2}{64})$. #include<cstdio> typedef unsigned int U; const int N=3010,M=100010,BUF=

【bzoj5102】[POI2018]Prawnicy 堆

题目描述 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大. 输入 第一行包含两个正整数n,k(1<=k<=n<=1000000),表示区间的数量. 接下来n行,每行两个正整数l,r(1<=l<r<=10^9),依次表示每个区间. 输出 第一行输出一个整数,即最大长度. 第二行输出k个正整数,依次表示选择的是输入文件中的第几个区间. 若有多组最优解,输出任意一组. 样例输入 6 3 3 8 4 12

[POI2018]Pow&#243;d?

题目大意: 一个$n\times m(nm\le5\times10^5)$的网格图,每个格子间有一个给定高度的挡板,每个格子的水位是$0\sim h(h\le10^9)$之间的一个整数.问总共有多少种可能的水位情况. 思路: 建立Kruskal重构树,实点代表原图中的格点,虚点代表若干个格点水位越过挡板进行合并后形成的新连通块.求出每个点所代表连通块的水位最大值$max[i]$和最小值$min[i]$,根结点的$max$值为$h$.进行树形DP.转移方程$f[i]=f[ch[i][0]]\tim

[POI2018]Prawnicy

题目大意: 有$n(n\le10^6)$个线段,每个线段覆盖的范围是$[l_i,r_i]$,要求从中选取$k(k\le10^6)$个线段使得这些线段覆盖范围的交集最大,求最大交集及任意一种方案. 思路: 对左端点排序,用堆维护右端点即可. 1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 #include<sys/mman.h> 6 #i

bzoj 5103 [POI2018]R&#243;?norodno??

这个题没有想出来.. 首先显然的一点是我们要对每种颜色做一次不重复的贡献计算. 同种颜色的贡献就是矩形的并.从网上查了资料,矩形面积并用的是扫描线,那么这个我们也可以用扫描线了. 我们考虑枚举横坐标,维护存在于当前横坐标的所有纵坐标的区间.一个性质是所有的矩形都是边长为k的正方形,那么在加入或删除一个区间时只可能影响到一个连续的区间.我们只需要对这个区间操作就行了. 我用的set维护,因为bzoj开O2,所以比其他数据结构要快一些,但是没有bitset快,要跑47s,记得加上fread,这个题的