zoukankan      html  css  js  c++  java
  • 【SCOI2019】—DAY2T1 湖之精灵的游戏(凸包+二分)

    考场debuffdebuff太严重了
    下来一眼沙比提


    考虑其实就是
    求一段区间
    Maxi[l,r](xi,yi)(x,y)Max|sum_{iin [l,r]}(x_i,y_i)*(x,y)|

    因为叉积不同方向会有正负
    由于有绝对值,可以拆成最大前缀和减去最小前缀和
    先只考虑最大前缀和
    MaxxiyyixMax sum{x_i}*y-sum{y_i}*x
    考虑2个前缀i,ji,jiijj大,则
    (xixj)y(yiyj)x>0(sum{x_i}-sum{x_j})*y-(sum{y_i}-sum{y_j})*x>0
    化一下就变成了
    (yiyk)(xixj)<yxfrac{(sum{y_i}-sum{y_k})}{(sum{x_i}-sum{x_j})}<frac y x

    就是一个很裸地斜率式子了,每次二分即可
    复杂度O(nlogn)O(nlogn)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ob==ib)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    const int N=1000005;
    int X[N],Y[N],n,m1,m2,q;
    struct point{
    	int x,y;
    	point(int _x=0,int _y=0):x(_x),y(_y){}
    	friend inline point operator +(const point &a,const point &b){
    		return point(a.x+b.x,a.y+b.y);
    	}
    	friend inline point operator -(const point &a,const point &b){
    		return point(a.x-b.x,a.y-b.y);
    	}
    	friend inline int operator *(const point &a,const point &b){
    		return (a.x*b.y-a.y*b.x);
    	}
    }p[N],up[N],down[N];
    inline void graham(){
    	up[1]=down[1]=point(0,0),up[2]=down[2]=p[1],m1=m2=2;
    	for(int i=2;i<=n;i++){
    		while(m1>=2&&(up[m1]-up[m1-1])*(p[i]-up[m1-1])>=0)m1--;
    		up[++m1]=p[i];
    		while(m2>=2&&(p[i]-down[m2-1])*(down[m2]-down[m2-1])>=0)m2--;
    		down[++m2]=p[i];
    	}
    }
    inline double calc(const point &a,double k){
    	return a.y-a.x*k;
    }
    inline double checkup(double k){
    	int l=1,res=l,r=m1;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(calc(up[mid],k)>=calc(up[mid+1],k))r=mid-1,res=mid;
    		else l=mid+1;
    	}
    	return calc(up[res],k);
    }
    inline double checkdown(double k){
    	int l=1,res=l,r=m2;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(calc(down[mid],k)<=calc(down[mid+1],k))r=mid-1,res=mid;
    		else l=mid+1;
    	}
    	return calc(down[res],k);
    }
    signed main(){
    	n=read();
    	for(int i=1;i<=n;i++)X[i]=read(),Y[i]=read();
    	for(int i=1;i<=n;i++)p[i]=p[i-1]+point(X[i],Y[i]);
    	graham();
    	q=read();
    	for(int i=1;i<=q;i++){
    		int x=read(),y=read();
    		double k=1.0*y/x;
    		double f1=checkup(k);
    		double f2=checkdown(k);
    		cout<<(int)round(x*(f1-f2))<<'
    ';
    	}
    }
    
  • 相关阅读:
    T-Sql 递归查询(给定节点查所有父节点、所有子节点的方法)
    禁用鼠标选中文字
    org.springframework.dao.InvalidDataAccessApiUsageException错误
    eclipse/myeclipse遇到的问题及解决方法
    WPF制作圆角窗体思路
    程序关闭后台进行
    转:Excel—“撤销工作表保护密码”的破解并获取原始密码
    C#压缩图片——高质量压缩方式
    【转载】.NET模拟POST登录并保持登录状态
    C#导出Excel,并设置简单格式
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145546.html
Copyright © 2011-2022 走看看