zoukankan      html  css  js  c++  java
  • Code Chef GEOCHEAT(凸包+旋转卡壳+随机化)

    题面

    传送门

    题解

    以下记(S_i={1,2,3,...,i})

    我们先用凸包+旋转卡壳求出直径的长度,并记直径的两个端点为(i,j)(如果有多条直径随机取两个端点)

    因为这个序列被(random\_shuffle)过,有(E(max(i,j))=O({2over 3}n)),即(max(i,j))的较大值的期望是(O({2over 3}n))。证明如下

    [egin{aligned} E(max(i,j)) &={1over n^2}sum_{k=1}^nk imes (2k-1)\ &={1over n^2}left(2sum_{k=1}^nk^2-sum_{k=1}^nk ight)\ &={1over n^2}left({2n(n+1)(2n+1)over 6}-{3n(n+1)over 6} ight)\ &={1over n^2}left({4n^3+3n^2-nover 6} ight)\ &=O({2over 3}n)\ end{aligned} ]

    假设(j>i),那么对于(S_{j+1},S_{j+2},...,S_n),它们的答案都一样。然后对于剩下的继续做下去就可以了

    我们来分析一下这玩意儿的时间复杂度是多少

    [T(n)=T({2over 3}n)+O(nlog n) ]

    [T(1)=O(1) ]

    嗯……我并不会主定理所以算不太动……不过我们可以考虑一个形如(n+{2over 3}n+{4over 9}n+...+1)的东西的求和,为了方便干脆直接将它写成无限求和的形式,那么可知它等于(3n),即(O(n))。那么这里也类似,所以我们完全没有道理地证明了(T(n)=O(nlog n))

    话说不知道如果序列不(random\_shufle)有没有办法搞……

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define inf 0x3f3f3f3f
    #define ll long long
    #define pi pair<int,int>
    #define fi first
    #define se second
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int K=-1,Z=0;
    inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
    void print(R ll x){
        if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++K]=z[Z],--Z);sr[++K]='
    ';
    }
    const int N=7.5e5+5;
    struct Point{
    	int x,y,id;
    	inline Point(){}
    	inline Point(R int xx,R int yy):x(xx),y(yy){}
    	inline Point operator +(const Point &b)const{return Point(x+b.x,y+b.y);}
    	inline Point operator -(const Point &b)const{return Point(x-b.x,y-b.y);}
    	inline ll operator *(const Point &b)const{return 1ll*x*b.y-1ll*y*b.x;}
    	inline ll norm()const{return 1ll*x*x+1ll*y*y;}
    }q[N],p[N];int top,n;ll res,ans[N];pi qwq;
    bool cmp(const Point &a,const Point &b){
    	R ll k=(a-p[0])*(b-p[0]);
    	return k?k>0:(a-p[0]).norm()<(b-p[0]).norm();
    }
    void solve(int r){
    	int k=0;p[0]=Point(inf,inf),top=0;
    	fp(i,1,r){
    		p[i]=q[i],p[i].id=i;
    		if(p[i].x<p[0].x||p[i].x==p[0].x&&p[i].y<p[0].y)k=i,p[0]=p[i];
    	}
    	swap(p[1],p[k]);
    	sort(p+2,p+1+r,cmp);
    	fp(i,1,r){
    		while(top>1&&(p[i]-p[top-1])*(p[top]-p[top-1])>=0)--top;
    		p[++top]=p[i];
    	}
    	p[top+1]=p[1];
    	res=0,qwq=make_pair(0,0);
    	for(R int i=1,j=2;i<=top;++i){
    		while((p[j+1]-p[i]).norm()>(p[j]-p[i]).norm())j=j%top+1;
    		if(cmax(res,(p[j]-p[i]).norm()))qwq=make_pair(p[i].id,p[j].id);
    		if(cmax(res,(p[j+1]-p[i+1]).norm()))qwq=make_pair(p[i+1].id,p[j+1].id);
    	}
    	if(qwq.fi>qwq.se)swap(qwq.fi,qwq.se);
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	fp(i,1,n)q[i].x=read(),q[i].y=read();
    	for(R int r=n;r!=1;r=qwq.se-1){
    		solve(r);
    		fp(i,qwq.se,r)ans[i]=res;
    	}
    	ans[1]=0;
    	fp(i,1,n)print(ans[i]);
    	return Ot(),0;
    }
    
  • 相关阅读:
    工具使用:Oracle数据库表转换为Mysql
    使用Spring框架下的完成对事务的操作
    使用Spring框架下的JdbcTemplate 完成对数据库的增删改查操作
    我的历程,从心开始
    验证码
    加载效果
    mybatis逆向工程
    lo4j配置文件
    springmvc拦截器
    如何在标题栏加入图标
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10729493.html
Copyright © 2011-2022 走看看