zoukankan      html  css  js  c++  java
  • SCOI2019 湖之精灵的游戏

    湖之精灵的游戏

    一个二维平面上有(n)个点,第(i)个点的坐标是((x_i,y_i)),你要和湖之精灵玩游戏。

    每次精灵会告诉你一个坐标((x,y)),连一条经过((0,0),(x,y))的直线,这会把平面分成两个部分(A,B)。你要选择一个区间([l,r]),那么计算的时候只会考虑编号在([l,r])之内的点。

    一个半平面的价值是这个半平面中,编号在([l,r])范围内的点与((0,0),(x,y))组成三角形的面积之和。

    你要选择一个半平面,精灵会选择另一个半平面,你需要最大化你得到的价值减去精灵得到的价值的结果。

    (m)轮游戏,对于每轮游戏输出这个最大值乘以(2)的结果。

    数据范围:(n,mleq 10^6,1leq x,yleq 1000)

    题解

    题面的意思就是每次询问给定((x,y)),让你自选区间([l,r]),求

    [max_{l,r}{|sum_{i=l}^r(xy_i-yx_i)|} ]

    利用前缀和思想观察绝对值式子

    [|x ext{sy}_r-y ext{sx}_r-(x ext{sy}_{l-1}-y ext{sx}_{l-1})| ]

    为了让这个绝对值最大化,我们只需要找到最大的(x ext{sy}_i-y ext{sx}_i)和最小的(x ext{sy}_j-y ext{sx}_j)。并且绝对值符号使得我们不必拘泥于大的减小的。

    怎么找最大值和最小值呢?老生常谈的斜率优化。

    [f=x ext{sy}_i-y ext{sx}_i ]

    [sy_i=frac{y}{x} ext{sx}_i+frac{f}{x} ]

    最大值做个上凸包,最小值做个下凸包。

    这个题也没有强制在线,直接双指针即可。

    时间复杂度(O(nlog n))

    struct point {int64 x,y;};
    
    IN point operator-(CO point&a,CO point&b){
    	return {a.x-b.x,a.y-b.y};
    }
    IN int64 cross(CO point&a,CO point&b){
    	return a.x*b.y-a.y*b.x;
    }
    
    CO int N=1e6+10;
    point p[N],up[N],dn[N];
    struct node {point p;int i;} q[N];
    int64 ans[N];
    
    int main(){
    	freopen("lake.in","r",stdin),freopen("lake.out","w",stdout);
    	int n=read<int>();
    	for(int i=1;i<=n;++i)
    		p[i].x=p[i-1].x+read<int>(),p[i].y=p[i-1].y+read<int>();
    	int s=1;
    	up[1]=p[0];
    	for(int i=1;i<=n;++i){
    		for(;s>=2 and cross(p[i]-up[s-1],up[s]-up[s-1])<=0;--s);
    		up[++s]=p[i];
    	}
    	int t=1;
    	dn[1]=p[0];
    	for(int i=1;i<=n;++i){
    		for(;t>=2 and cross(p[i]-dn[t-1],dn[t]-dn[t-1])>=0;--t);
    		dn[++t]=p[i];
    	}
    	int m=read<int>();
    	for(int i=1;i<=m;++i)
    		read(q[i].p.x),read(q[i].p.y),q[i].i=i;
    	sort(q+1,q+m+1,[&](CO node&a,CO node&b)->bool{
    		return cross(a.p,b.p)<0;
    	});
    	for(int i=1,j=1;i<=m;++i){
    		for(;j+1<=s and cross(q[i].p,up[j+1]-up[j])>0;++j);
    		ans[q[i].i]+=cross(q[i].p,up[j]);
    	}
    	sort(q+1,q+m+1,[&](CO node&a,CO node&b)->bool{
    		return cross(a.p,b.p)>0;
    	});
    	for(int i=1,j=1;i<=m;++i){
    		for(;j+1<=t and cross(q[i].p,dn[j+1]-dn[j])<0;++j);
    		ans[q[i].i]-=cross(q[i].p,dn[j]);
    	}
    	for(int i=1;i<=m;++i) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    ZOJ 1002 Fire Net (火力网)
    UVa OJ 117 The Postal Worker Rings Once (让邮差只走一圈)
    UVa OJ 118 Mutant Flatworld Explorers (变体扁平世界探索器)
    UVa OJ 103 Stacking Boxes (嵌套盒子)
    UVa OJ 110 MetaLoopless Sorts (无循环元排序)
    第一次遇到使用NSNull的场景
    NSURL使用浅析
    从CNTV下载《小小智慧树》
    NSDictionary and NSMutableDictionary
    Category in static library
  • 原文地址:https://www.cnblogs.com/autoint/p/13097943.html
Copyright © 2011-2022 走看看