zoukankan      html  css  js  c++  java
  • 计算几何

    谢Achen提醒,差点忘了有计算几何这东西。

    poj2187 平面最远点对,凸包+旋转卡壳模板

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=5e4+7;
    int n;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const double eps=1e-10;
    double pf(double x){return x*x;}
    inline int dcmp(const long double &x){return abs(x)<eps? 0:(x>0? 1:-1);}
    
    struct Xl{
    	double x,y;
    	Xl(double x=0.,double y=0.):x(x),y(y){}
    	bool operator == (const Xl &b) const{return (!dcmp(x-b.x))&&(!dcmp(y-b.y));}
    	bool operator <  (const Xl &b) const{return !dcmp(x-b.x)? y<b.y:x<b.x;}
    	Xl operator + (const Xl &b) const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl &b) const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const double &b) const{return Xl(x*b,y*b);}
    	Xl operator / (const double &b) const{return Xl(x/b,y/b);}
    	double len() const{return pf(x)+pf(y);}
    }node[maxn],zz[maxn];
    int t;
    
    double D_(const Xl& a,const Xl& b){return a.x*b.x+a.y*b.y;}
    double X_(const Xl& a,const Xl& b){return a.x*b.y-a.y*b.x;}
    
    bool cmp(const Xl& a,const Xl& b){
    	return dcmp(X_(a-node[1],b-node[1]))==0? 
    			(a-node[1]).len()<(b-node[1]).len() : dcmp(X_(a-node[1],b-node[1]))>0;
    }
    
    void graham() {
    	For(i,2,n) if(node[i]<node[1]) swap(node[i],node[1]);
    	sort(node+2,node+n+1,cmp);
    	zz[++t]=node[1]; zz[++t]=node[2];
    	For(i,3,n) {
    		while(t>1&&dcmp(X_(zz[t]-zz[t-1],node[i]-zz[t]))<=0) --t;// "<" -> WA
    		zz[++t]=node[i];
    	}
    }
    
    double RC() {
    	zz[t+1]=zz[1];
    	int now=2;double rs=0;
    	For(i,1,t) {
    		while(X_(zz[i+1]-zz[i],zz[now]-zz[i])<X_(zz[i+1]-zz[i],zz[now+1]-zz[i]))
    			if((++now)>t) now=1;
    		rs=max(rs,(zz[now]-zz[i]).len());
    	}
    	return rs;
    }
    
    int main() {
    	read(n);
    	For(i,1,n) {
    		read(node[i].x); 
    		read(node[i].y);
    	}
    	graham();
    	printf("%lld",(ll)RC());
    	return 0;
    }
    /*
    4
    0 0
    0 1
    1 3
    1 0
    */
    

      

    hdu1007 平面最近点对模板

    分治,时间复杂度是nlog(n)的,由鸽巢原理可知,在那个for套for的循环里面枚举实际上最多只会枚举6个点(不会证)

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=1e5+7;
    const db INF=1e18;
    int n; db ans;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-10;
    db pf(db x){return x*x;}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator + (const Xl& b)const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b)const{return Xl(x-b.x,y-b.y);}
    	db len()const{return sqrt(pf(x)+pf(y));}
    }node[maxn],zz[maxn];
    
    bool cmp1(const Xl& a,const Xl& b) {
    	return a.x==b.x? a.y<b.y : a.x<b.x;
    }
    
    bool cmp2(const Xl& a,const Xl& b) {
    	return a.y<b.y;
    }
    
    void solve(int l,int r) {
    	if(l>=r) return;
    	if(l+1==r) {
    		ans=min(ans,(node[l]-node[r]).len());
    		return;
    	}
    	int mid=(l+r)>>1,t=0;
    	solve(l,mid); solve(mid+1,r);
    	For(i,l,r) if(fabs(node[i].x-node[mid].x)<ans) zz[++t]=node[i];
    	sort(zz+1,zz+t+1,cmp2);
    	For(i,1,t) for(int j=i+1;j<=t&&zz[j].y-zz[i].y<ans;++j) 
    		ans=min(ans,(zz[j]-zz[i]).len());
    }
    
    int main() {
    	read(n);db x,y;
    	while(n) {
    		For(i,1,n) {
    			scanf("%lf%lf",&x,&y);
    			node[i]=Xl(x,y);
    		}
    		sort(node+1,node+n+1,cmp1);
    		ans=INF; solve(1,n);
    		printf("%.2f
    ",ans/2);
    		read(n);
    	}
    	return 0;
    }
    

    poj3335 判断多边形内核存在 ,半平面交模板

    注意onleft中要写>=而不是>这样一个点的情况才能把边保留下来

    最后不能也判面积否则就把一个点的情况判掉了。

    为此debug了一下午。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    const int maxn=300+7;
    int T,n;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const double eps=1e-8;
    inline int dcmp(const long double &x){return fabs(x)<eps? 0:(x>0? 1:-1);}
    
    struct Xl{
    	double x,y;
    	Xl(double x=0.,double y=0.):x(x),y(y){}
    	Xl operator + (const Xl &b) const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl &b) const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const double &b) const{return Xl(x*b,y*b);}
    	double angle() const{return atan2(y,x);} 
    }node[maxn],p[maxn];
    
    double D_(const Xl& a,const Xl& b){return a.x*b.x+a.y*b.y;}
    double X_(const Xl& a,const Xl& b){return a.x*b.y-a.y*b.x;}
    
    struct Li{
    	Xl u,v; double rad;
    	Li(Xl u=Xl(0.,0.),Xl v=Xl(0.,0.)):u(u),v(v){rad=(v-u).angle();}
    	bool operator < (const Li &b) const{return rad<b.rad;}
    }li[maxn],zz[maxn];
    
    Xl lijd(const Li &a,const Li& b) {
    	Xl x=a.v-a.u,y=b.v-b.u,z=a.u-b.u;
    	long double c=X_(y,z);
    	long double t=c/(c+X_(x+z,y));
    	return a.u+x*t;
    }
    
    bool onleft(const Xl &a,const Li &l) {return dcmp(X_(l.v-l.u,a-l.u))>=0;}//">" -> WA
    
    bool work() {
    	For(i,1,n-1) li[i]=Li(node[i],node[i+1]);
    	li[n]=Li(node[n],node[1]);
    	sort(li+1,li+n+1);
    	int s=1,t=0; zz[++t]=li[1];
    	For(i,2,n) {
    		while(s<t&&!onleft(p[t-1],li[i])) t--;
    		while(s<t&&!onleft(p[s],li[i])) s++;
    		zz[++t]=li[i];
    		if(!dcmp(X_(li[i].v-li[i].u,zz[t-1].v-zz[t-1].u)))
    			if(onleft(li[i].u,zz[--t])) zz[t]=li[i];
    		if(s<t) p[t-1]=lijd(zz[t],zz[t-1]);
    	}
    	while(s<t&&!onleft(p[t-1],li[s])) --t;
    	return t-s>1;//
    }
    
    int main() {
    	read(T);
    	ll x,y;
    	while(T--) {
    		read(n);
    		For(i,1,n) {
    			read(x); read(y);
    			node[n-i+1]=Xl(x,y);
    		}
    		if(work()) printf("YES
    ");
    		else printf("NO
    ");
    	}
    	return 0;
    }
    /*
    1
    11 29 3 88 16 89 33 95 59 97 70 56 31 87 97 31 44 28 21 21 60 7 52 
    */
    

      

    bzoj2168 半平面交模板 onleft的>=改成>就过了

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=500+7;
    int n,m;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-8;
    inline int dcmp(const db &x){return fabs(x)<eps? 0 : (x>0? 1:-1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator + (const Xl& b)const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b)const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const db& b)const{return Xl(b*x,b*y);}
    	db angle()const{return atan2(y,x);}
    }node[maxn],p[maxn];
    
    db D_(const Xl& a,const Xl& b){return a.x*b.x+a.y*b.y;}
    db X_(const Xl& a,const Xl& b){return a.x*b.y-a.y*b.x;}
    
    struct Li{
    	Xl u,v; db rad;
    	Li(Xl u=Xl(0.,0.),Xl v=Xl(0.,0.)):u(u),v(v){rad=(v-u).angle();}
    	bool operator < (const Li& b)const{return rad<b.rad;}
    }li[maxn],zz[maxn];
    int tot;
    
    Xl lijd(const Li& a,const Li& b) {
    	Xl x=a.v-a.u,y=b.v-b.u,z=a.u-b.u;
    	db c=X_(z,y);
    	db t=c/(c+X_(y,x+z));
    	return a.u+x*t;
    }
    
    bool onleft(const Xl& a,const Li& l){return X_(l.v-l.u,a-l.u)>0;}
    
    db HPI() {
    	sort(li+1,li+tot+1);
    	int s=1,t=0; zz[++t]=li[1];
    	For(i,2,tot) {
    		while(s<t&&!onleft(p[t-1],li[i])) t--;
    		while(s<t&&!onleft(p[s],li[i])) s++;
    		zz[++t]=li[i];
    		if(!dcmp(X_(li[i].v-li[i].u,zz[t-1].v-zz[t-1].u))) 
    			if(onleft(li[i].u,zz[--t])) zz[t]=li[i];
    		if(s<t) p[t-1]=lijd(zz[t],zz[t-1]);
    	}
    	while(s<t&&!onleft(p[t-1],li[s])) t--;
    	if(t-s<2) return 0.000;
    	db rs=0; p[t]=lijd(zz[t],zz[s]);
    	For(i,s+1,t-1) rs+=X_(p[i]-p[s],p[i+1]-p[s]);
    	return fabs(rs)/2.0;
    }
    
    int main() {
    	read(n); ll x,y;
    	For(i,1,n) {
    		read(m);
    		For(j,1,m) {
    			read(x); read(y);
    			node[j]=Xl(x,y);
    		}
    		For(j,1,m-1) li[++tot]=Li(node[j],node[j+1]);
    		li[++tot]=Li(node[m],node[1]);
    	}
    	printf("%.3f",HPI());
    	return 0;
    }
    

      

    bzoj4445 半平面交

    简单推推式子

    bzoj上精度坑人,最好开long double

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db long double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=2e5+7;
    const db PI=acos(-1),eps=1e-18;
    int n;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    db pf(const db& x){return x*x;}
    inline int dcmp(const long double &x){return abs(x)<eps? 0:(x>0? 1:-1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator + (const Xl& b)const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b)const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const db& b)const{return Xl(x*b,y*b);}
    	db len()const{return sqrt(pf(x)+pf(y));}
    	double angle() const{return atan2(y,x);}
    }node[maxn],p[maxn],R;
    db sr;
    
    double D_(const Xl& a,const Xl& b){return a.x*b.x+a.y*b.y;}
    double X_(const Xl& a,const Xl& b){return a.x*b.y-a.y*b.x;}
    
    struct Li{
    	Xl u,v;db rad;
    	Li(Xl u=Xl(0.,0.),Xl v=Xl(0.,0.)):u(u),v(v){rad=(v-u).angle();}
        bool operator < (const Li &b) const{return rad<b.rad;}
    }li[maxn],zz[maxn];
    int tot;
    
    bool onleft(const Xl& a,const Li& l) { return dcmp(X_(l.v-l.u,a-l.u))>0;}
    
    bool get_line(Xl R,db c) {
    	db a=-R.y,b=R.x,x,y;
    	if(dcmp(a)==0&&dcmp(b)==0) {
    		if(dcmp(c)>=0) return 1;
    		return 0;
    	}
    	Xl u,v;
    	if(dcmp(a)==0) {
    		y=-c/b;
    		u=Xl(0,y); v=Xl(1,y);
    		if(dcmp(b)<0) swap(u,v);
    	}
    	else if(dcmp(b)==0) {
    		x=-c/a;
    		u=Xl(x,1); v=Xl(x,0);
    		if(dcmp(a)<0) swap(u,v);
    	}
    	else {
    		x=0; y=-c/b;
    		u=Xl(x,y);
    		x=1; y=(-a-c)/b;
    		v=Xl(x,y);
    		if(dcmp(b)<0) swap(u,v);
    	}
    	li[++tot]=Li(u,v);
    	return 1;
    }
    
    Xl lijd(const Li& a,const Li& b) {
    	Xl x=a.v-a.u,y=b.v-b.u,z=a.u-b.u;
    	db S=X_(z,y);
    	db t=S/(S+X_(y,x+z));
    	return a.u+x*t;
    }
    
    db HPL() {
    	sort(li+1,li+tot+1);
    	int s=1,t=0;
    	zz[++t]=li[1];
    	For(i,2,tot) {
    		while(s<t&&!onleft(p[t-1],li[i])) t--;
    		while(s<t&&!onleft(p[s],li[i])) s++;
    		zz[++t]=li[i];
    		if(dcmp(X_(li[i].v-li[i].u,zz[t-1].v-zz[t-1].u))==0)
    			if(onleft(li[i].u,zz[--t])) zz[t]=li[i];
    		if(s<t) p[t-1]=lijd(zz[t],zz[t-1]);
    	}
    	while(s<t&&!onleft(p[t-1],li[1])) t--;
    	if(s+1>t-1) return 0.0;
    	db rs=0; p[t]=lijd(zz[t],zz[s]);
    	For(i,s+1,t-1) rs+=X_(p[i]-p[s],p[i+1]-p[s]);
    	return dcmp(rs)==0? 0:fabs(rs)/2.0;
    }
    
    db work() {
    	For(i,2,n-1) {
    		R=node[1]-node[2]-node[i]+node[i+1];
    		sr=X_(node[i],node[i+1])-X_(node[1],node[2]);
    		if(!get_line(R,sr)) return 0.0;
    	}
    	R=node[1]-node[2]-node[n]+node[1];
    	sr=X_(node[n],node[1])-X_(node[1],node[2]);
    	if(!get_line(R,sr)) return 0.0;
    	return HPL();
    }
    
    int main() {
    	read(n); ll x,y;
    	For(i,1,n) {
    		read(x); read(y);
    		node[i]=Xl(x,y);
    	}
    	db S=0;
    	For(i,2,n-1) S+=X_(node[i]-node[1],node[i+1]-node[1]);
    	S=fabs(S)/2.0;
    	For(i,1,n-1) li[i]=Li(node[i],node[i+1]);
    	li[n]=Li(node[n],node[1]); tot=n;
    	printf("%.4Lf",work()/S);
    	return 0;
    }
    /*
    3
    0 0
    1 0
    0 1
    */

    hdu3007 最小圆覆盖模板

    数学一本通上的问题分析要把人绕晕,看代码还是要直观些

    这个做法复杂度是O(n)的,当加入圆的顺序随机时,因为三点定一圆,所以不在圆内概率是3/i

    所以可以用random_shuffle()这个函数让点随机(要用到algorithm这个头文件)

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=500+7;
    int n;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-10;
    db pf(db x){return x*x;}
    inline int dcmp(const long db &x){return abs(x)<eps? 0:(x>0? 1:-1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator + (const Xl& b)const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b)const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const db& b)const{return Xl(x*b,y*b);}
    	Xl operator / (const db& b)const{return Xl(x/b,y/b);}
    	db len()const{return sqrt(pf(x)+pf(y));}
    }node[maxn],c;
    
    db D_(const Xl& a,const Xl& b){return a.x*b.x+a.y*b.y;}
    db X_(const Xl& a,const Xl& b){return a.x*b.y-a.y*b.x;}
    
    db r;
    
    Xl cir_enter(const Xl& a,const Xl& b,const Xl& c) {
    	db bx=b.x-a.x,by=b.y-a.y,bpf=pf(bx)+pf(by);
        db cx=c.x-a.x,cy=c.y-a.y,cpf=pf(cx)+pf(cy);
        db area=2*(bx*cy-by*cx);
        db x=(cy*bpf-by*cpf)/area;
        db y=(bx*cpf-cx*bpf)/area;
        return Xl(x+a.x,y+a.y);
    }
    
    void mincir() {
    	random_shuffle(node+1,node+n+1);
    	c=node[1]; r=0;
    	For(i,2,n) if(dcmp((node[i]-c).len()-r)>0) {
    		c=node[i]; r=0;
    		For(j,1,i-1) if(dcmp((node[j]-c).len()-r)>0) {
    			c=(node[i]+node[j])/2;
    			r=(node[i]-c).len();
    			For(k,1,j-1) if(dcmp((node[k]-c).len()-r)>0) {
    				c=cir_enter(node[i],node[j],node[k]);
    				r=(node[i]-c).len();
    			}
    		}
    	}
    }
    
    int main() {
    	read(n);db x,y;
    	while(n) {
    		For(i,1,n) {
    			scanf("%lf%lf",&x,&y);
    			node[i]=Xl(x,y);
    		}
    		mincir();
    		printf("%.2f %.2f %.2f
    ",c.x,c.y,r);
    		read(n);
    	}
    	return 0;
    }
    /*
    3
    1.00 1.00
    3.00 0.00
    3.00 2.00
    0
    */
    

      

    bzoj4750 妖怪

    上凸包

    这道题我的思维方式有点奇怪

    对于每个妖怪我们看做一个点$(x,y)$

    那么它的战斗力为$frac{a+b}{a} imes x + frac{a+b}{b} imes y$

    我们考虑对于一个固定的$(a,b)$,战斗力最大的是上凸壳上的一个点

    现在反过来考虑对于一个点$(x_0,y_0)$,什么时候它是战斗力最大的

    令$r=frac{b}{a}$

    那么有$r imes x_0 + y_0 > r imes x_1 + y_1 $

    1) $x_0 > x_1$:$r geq - frac{y_0-y_1}{x_0-x_1}$

    2) $x_0 < x_1$:$r leq - frac{y_1-y_0}{x_1-x_0}$

    我们发现,对于上凸壳的一个点a,假如它左边的点是b,右边的点是c

    那么$r$就是在$-angle(a-b)$到$-angle(c-a)$之间,并且$r geq 0$(因为$a,b geq 0$)

    对于所有点中一个战斗力最大的那个点$(x,y)$,什么样的$(a,b)$可以使得它的战斗力尽量小呢

    $frac{a+b}{a} imes x = frac{a+b}{b} imes y$

    $frac{b}{a} = frac{y}{x}$

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=1e6+7;
    const db INF=1e16;
    int n;
    db ans=INF;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-12;
    int dcmp(const db &x){return fabs(x)<=eps? 0:(x<0? -1:1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator - (const Xl& b) const{return Xl(x-b.x,y-b.y);}
    	bool operator < (const Xl& b) const{return dcmp(x-b.x)==0? y<b.y:x<b.x;}
    	db angle() const{return y/x;}
    }node[maxn],zz[maxn];
    
    db X_(const Xl& a,const Xl& b) {return a.x*b.y-a.y*b.x;}
    
    bool onleft(const Xl& p,const Xl& u,const Xl& v) {
    	return dcmp(X_(v-u,p-u))>=0;
    }
    
    db p[maxn];
    
    db get_ans(const Xl& p,db l,db r) {
    	l=-l; r=-r; l=max(l,0.0); r=max(r,0.0);
    	db t=p.y/p.x;
    	if(t>r) t=r;
    	else if(t<l) t=l;
    	if(dcmp(t)==0) return INF;
    	db a=100,b=a*t;
    	return (a+b)/a*p.x+(a+b)/b*p.y;
    }
    
    void solve() {
    	sort(node+1,node+n+1);
    	int t=0;
    	For(i,1,n) {
    		while(t&&node[i].x==zz[t].x) t--;
    		while(t>1&&onleft(node[i],zz[t-1],zz[t])) t--;
    		zz[++t]=node[i];
    	}
    	For(i,1,t-1) p[i]=(zz[i+1]-zz[i]).angle();
    	p[t]=-INF;
    	For(i,1,t) ans=min(ans,get_ans(zz[i],p[i-1],p[i]));
    }
    
    int main() {
    	read(n); db x,y;
    	For(i,1,n) {
    		read(x); read(y);
    		node[i]=Xl(x,y);
    	}
    	solve();
    	printf("%.4f",ans);
    	return 0;
    }
    

      

    bzoj1069 最大土地面积

    没有什么脑子的模板题,一直以为这道题很难,然后今天看了看数据范围……

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=4000+7;
    int n;
    db ans[maxn][maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-10;
    db pf(db x){return x*x;}
    int dcmp(db x){return fabs(x)<=eps? 0:(x>0? 1:-1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	bool operator < (const Xl& b) const{return dcmp(x-b.x)==0? y<b.y:x<b.x;}
    	Xl operator + (const Xl& b) const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b) const{return Xl(x-b.x,y-b.y);}
    	db len() const{return pf(x)+pf(y);}
    }node[maxn],zz[maxn];
    int t;
    
    db D_(const Xl& a,const Xl& b) {return a.x*b.x+a.y*b.y;}
    db X_(const Xl& a,const Xl& b) {return a.x*b.y-a.y*b.x;}
    
    bool cmp(const Xl& a,const Xl& b) {
    	return dcmp(X_(a-node[1],b-node[1]))==0?
    			(a-node[1]).len()<(b-node[1]).len() : dcmp(X_(a-node[1],b-node[1]))>0;
    }
    
    void graham() {
    	For(i,2,n) if(node[i]<node[1]) swap(node[i],node[1]);
    	sort(node+2,node+n+1,cmp);
    	zz[++t]=node[1]; zz[++t]=node[2];
    	For(i,3,n) {
    		while(t>1&&dcmp(X_(zz[t]-zz[t-1],node[i]-zz[t])<=0)) --t;
    		zz[++t]=node[i];
    	}
    }
    
    void RC() {
    	For(i,1,t) zz[i+t]=zz[i]; zz[0]=zz[t];
    	int now; Xl p;
    	For(i,1,t) {
    		now=(i+1)%t;
    		For(j,i+1,i+t-1) {
    			p=zz[j]-zz[i];
    			while(X_(p,zz[now]-zz[i])<X_(p,zz[now+1]-zz[i])) now=(now+1)%t;
    			ans[i][j]=X_(p,zz[now]-zz[i]);
    		}
    	} 
    }
    
    int main() {
    	read(n); db x,y;
    	For(i,1,n) {
    		scanf("%lf%lf",&x,&y);
    		node[i]=Xl(x,y);
    	}
    	graham();
    	RC(); db totans=0;
    	For(i,1,t) For(j,i+1,t) 
    		totans=max(totans,ans[i][j]+ans[j][i+t]);
    	printf("%.3lf",totans/2);
    	return 0;
    }
    

      

    bzoj2388 旅行规划

    分块+凸包+神奇的三分

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=2e5+7,maxt=500+7;
    const ll INF=1e16;
    int n,m,sz,tot;
    ll s[maxn],A[maxn],B[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-8;
    int dcmp(db x) {return fabs(x)<=eps? 0:(x<0? -1:1);}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator - (const Xl& b) const{return Xl(x-b.x,y-b.y);}
    	bool operator < (const Xl& b) const{return dcmp(x-b.x==0)? y<b.y : x<b.x;}
    }node[maxn],p[maxt][maxt];
    int top[maxt];
    
    db X_(const Xl& a,const Xl& b) {return a.x*b.y-a.y*b.x;}
    db D_(const Xl& a,const Xl& b) {return a.x*b.x+a.y*b.y;}
    
    void get_ham(int pos) {
    	int l=max(pos*sz,1),r=min((pos+1)*sz-1,n);
    	For(i,l,r) node[i]=Xl(i,s[i]);
    	int t=0; p[pos][++t]=node[l];
    	For(i,l+1,r) {
    		while(t>1&&dcmp(X_(p[pos][t]-p[pos][t-1],node[i]-p[pos][t-1]))>=0) t--;
    		p[pos][++t]=node[i];
    	}
    	top[pos]=t;
    }
    
    void pd(int pos) {
    	if(A[pos]==0&&B[pos]==0) return;
    	int l=max(pos*sz,1),r=min((pos+1)*sz-1,n);
    	For(i,l,r) s[i]+=A[pos]+(i-l)*B[pos];
    	A[pos]=B[pos]=0;
    }
    
    void chge(int l,int r,ll x) {
    	pd(l/sz); pd(r/sz);
    	if(l/sz==r/sz) {
    		For(i,l,r) s[i]+=x*(i-l+1);
    		get_ham(l/sz);
    		For(i,r+1,min((r/sz+1)*sz-1,n)) s[i]+=x*(r-l+1);
    		For(i,l/sz+1,tot) A[i]+=(r-l+1)*x;
    		return;
    	}
    	For(i,l,min((l/sz+1)*sz-1,n)) s[i]+=x*(i-l+1);
    	get_ham(l/sz);
    	For(i,max((r/sz)*sz,1),r) s[i]+=x*(i-l+1);
    	For(i,r+1,min((r/sz+1)*sz-1,n)) s[i]+=x*(r-l+1);
    	get_ham(r/sz);
    	For(i,l/sz+1,r/sz-1) A[i]+=(i*sz-l+1)*x,B[i]+=x;
    	For(i,r/sz+1,tot) A[i]+=(r-l+1)*x;
    }
    
    ll cal(int pos) {return A[pos/sz]+B[pos/sz]*(pos-(pos/sz)*sz)+s[pos];}
    
    ll get_ans(int pos) {
    	int l=1,r=top[pos],mid; ll a,b,c;
    	while(l<=r) {
    		if(l+1>=r) return max(cal(p[pos][l].x),cal(p[pos][r].x));
    		mid=(l+r)>>1;
    		a=cal(p[pos][mid-1].x);
    		b=cal(p[pos][mid].x);
    		c=cal(p[pos][mid+1].x);
    		if(a<b&&b<c) l=mid+1;
    		else if(a>b&&b>c) r=mid-1;
    		else return b;
    	}
    	return 0;
    }
    
    ll Yth(int l,int r) {
    	pd(l/sz); pd(r/sz);
    	ll rs=-INF;
    	if(l/sz==r/sz) {
    		For(i,l,r) rs=max(rs,s[i]);
    		return rs;
    	}
    	For(i,l,min((l/sz+1)*sz-1,n)) rs=max(rs,s[i]);
    	For(i,max((r/sz)*sz,1),r) rs=max(rs,s[i]);
    	For(i,l/sz+1,r/sz-1) rs=max(rs,get_ans(i));
    	return rs;
    }
    
    int main() {
    	read(n); sz=min((int)sqrt(n),200)+1; tot=n/sz;
    	ll op,l,r,x;
    	For(i,1,n) read(s[i]),s[i]+=s[i-1];
    	For(i,0,tot) get_ham(i);
    	read(m); 
    	For(i,1,m) {
    		read(op); read(l); read(r);
    		if(op) printf("%lld
    ",Yth(l,r));
    		else {
    			read(x);
    			chge(l,r,x);
    		}
    	}
    	return 0;
    }
    

    bzoj1038瞭望塔

    半平面交+线段最小距离 板子

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=1000+7;
    int n;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    const db eps=1e-14,INF=1e30;
    int dcmp(const db x){return fabs(x)<=eps? 0:(x>0? 1:-1);}
    db pf(const db x){return x*x;}
    
    struct Xl{
    	db x,y;
    	Xl(db x=0.,db y=0.):x(x),y(y){}
    	Xl operator + (const Xl& b) const{return Xl(x+b.x,y+b.y);}
    	Xl operator - (const Xl& b) const{return Xl(x-b.x,y-b.y);}
    	Xl operator * (const db& b) const{return Xl(x*b,y*b);}
    	Xl operator / (const db& b) const{return Xl(x/b,y/b);}
    	db angle() const{return atan2(y,x);}
    	db len() const{return sqrt(pf(x)+pf(y));}
    }node[maxn],p[maxn];
    
    db X_(const Xl& a,const Xl& b) {return a.x*b.y-a.y*b.x;}
    db D_(const Xl& a,const Xl& b) {return a.x*b.x+a.y*b.y;}
    
    struct Li{
    	Xl u,v; db rad;
    	Li(){}
    	Li(Xl u,Xl v):u(u),v(v){rad=(v-u).angle();}
    	bool operator < (const Li& b) const{return rad<b.rad;}
    }li[maxn],zz[maxn];
    
    bool onleft(const Xl& a,const Li& l) {return dcmp(X_(l.v-l.u,a-l.u))>0;}
    Xl lijd(const Li& a,const Li& b) {
    	Xl x=a.v-a.u,y=b.v-b.u,z=a.u-b.u;
    	db t=X_(z,y);
    	t=t/(t+X_(y,x+z));
    	return a.u+x*t;
    }
    
    db xdjl(Li a,Li b) {
    	return min((a.u-b.u).len(),(a.v-b.v).len());
    }
    
    db get_ans(db l,db r,Li a,Li b) {
    	if(l>r) return INF;
    	Xl x=a.v-a.u,y=b.v-b.u;
    	a.u=a.u+x*((l-a.u.x)/(a.v.x-a.u.x));
    	b.u=b.u+y*((l-b.u.x)/(b.v.x-b.u.x));
    	x=a.v-a.u; y=b.v-b.u;
    	a.v=a.u+x*((r-a.u.x)/(a.v.x-a.u.x));
    	b.v=b.u+y*((r-b.u.x)/(b.v.x-b.u.x));
    	return xdjl(a,b);
    }
    
    db HPI() {
    	sort(li+1,li+n);
    	int s=1,t=0; zz[++t]=li[1];
    	For(i,2,n-1) {
    		while(s<t&&!onleft(p[t-1],li[i])) t--;
    		while(s<t&&!onleft(p[s],li[i])) s++;
    		zz[++t]=li[i];
    		if(s<t&&dcmp(li[i].rad-zz[t-1].rad)==0) if(onleft(li[i].u,zz[--t])) zz[t]=li[i];
    		if(s<t) p[t-1]=lijd(zz[t],zz[t-1]);
    	}
    	while(s<t&&!onleft(p[t-1],li[s])) t--;
    	p[s-1].x=-INF;
    	p[t+1].x=INF;
    	db rs=INF,l,r; int pos=s;
    	For(i,1,n-1) {
    		while(pos<t&&p[pos].x<node[i].x) ++pos;
    		l=max(node[i].x,p[pos-1].x); r=min(node[i+1].x,p[pos].x);
    		rs=min(rs,get_ans(l,r,zz[pos],Li(node[i],node[i+1])));
    		while(pos<t&&p[pos].x<=node[i+1].x) {
    			++pos;
    			l=max(node[i].x,p[pos-1].x); r=min(node[i+1].x,p[pos].x);
    			rs=min(rs,get_ans(l,r,zz[pos],Li(node[i],node[i+1])));
    		}
    	}
    	return rs;
    }
    
    int main() {
    	read(n);
    	For(i,1,n) scanf("%lf",&node[i].x);
    	For(i,1,n) scanf("%lf",&node[i].y);
    	For(i,1,n-1) li[i]=Li(node[i],node[i+1]);
    	printf("%.3f",HPI()); 
    	return 0;
    }
    

      

  • 相关阅读:
    面向对象的程序设计-2-创建对象
    面向对象的程序设计-1-理解对象
    react组件的生命周期
    react-router 组件式配置与对象式配置小区别
    mobx @computed的解读
    十分钟介绍mobx与react
    less学习
    git-简单流程(学习笔记)
    几种视频编码器的编译及使用方法
    一位程序员工作10年总结的13个忠告
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8462437.html
Copyright © 2011-2022 走看看