[Study notes] and Minkowski

It was still a mutter I N long stuff

Minkowski and is a strange thing

He was a long way

$S={a+b | a \bel A , b \bel B}$

AB point may be set, but also vector set (apparently)

 

He can deal with some strange things

For instance, we look at this problem

JSOI2018 war

It is to determine whether you find the vector AB is present in the Minkowski and in its requirements

Then you put on the board finished it

 

Well, you probably understand what Minkowski and

We now learn how to write

The point on we intuitively understood Minkowski certain point on the convex hull of the set of points constituting

So we find all points of violence once again seek to finish the convex hull complexity is O (| A | * | B |)

 

It looks not very gifted certainly can be optimized

We found a good spot on the nature of its convex hull slope is monotonic it is clear that the optimization can be TwoPointers

We direct observation which expand on it outside

 

Code implements throw here

//Love and Freedom.
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define inf 20021225
#define ll long long
#define db double
#define eps 1e-8
#define N 200010
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct then
{
    db x,y;
    then(){}
    poi(db _x,db _y){x=_x,y=_y;}
};
typedef then vec;
Case operator + (a case, case b) { return object (A.x + bx, a.y + b.y);}
Case operator - (a case, case b) { return Case (ax-bx, AY by);}
Case operator * (case a, b db) { return object (ax + b, y * p);}
Case operator / (case a, b db) { return Case (x / b, and y / b);}
db cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
db dot(vec a){return a.x*a.x+a.y*a.y;}
db only (case a) { return sqrt (dot (a));}
db dis (then a, then b) { return len (b- a);}
then p0;
int dcmp(db x){return x>eps?1:x<-eps?-1:0;}
bool cmp(poi p1,poi p2){return dcmp(cross(p1-p0,p2-p0))==1||(dcmp(cross(p1-p0,p2-p0))==0&&dis(p0,p1)<dis(p0,p2));}
int gethull(poi *p,poi *h,int n)
{
    p0=poi{1e18,1e18}; int id=0;
    for(int i=1;i<=n;i++)
        if(dcmp(p[i].x-p0.x)<0||(dcmp(p[i].x-p0.x)==0&&dcmp(p[i].y-p0.y)<0))
            id=i,p0=p[i];
    swap(p[1],p[id]); sort(p+2,p+n+1,cmp);
    int top=2; h[1]=p[1],h[2]=p[2];
    for(int i=3;i<=n;i++)
    {
        while(top>2&&dcmp(cross(p[i]-h[top-1],h[top]-h[top-1]))>=0)    top--;
        h[++top]=p[i];
    }
    return top;
}
poi A[N],B[N],p[N],C[N]; int na,nb,nc;
void minkowski()
{
    A [ 1 ] = A [ 1 ], B [NB + 1 ] = B [ 1 ];
    C[nc=1]=A[1]+B[1]; int i=1,j=1;
    while(i<=na&&j<=nb)
    {
        vec v1=A[i+1]+B[j]-C[nc],v2=A[i]+B[j+1]-C[nc];
        if(dcmp(cross(v1,v2))>=0)
            C[++nc]=A[i+1]+B[j],i++;
        else
            C[++nc]=A[i]+B[j+1],j++;
    }
    while(i<=na)    C[++nc]=A[i]+B[j],i++;
    while(j<=nb)    C[++nc]=A[i]+B[j],j++;
}
bool check (then w)
{
    if((dcmp(cross(w-C[1],C[nc]-C[1]))==0&&dis(C[nc],C[1])>=dis(C[1],w))||(dcmp(cross(w-C[1],C[2]-C[1]))==0 && dis(C[1],w)<=dis(C[2],C[1])))    return 1;
    int l=2,r=nc,ans=0;
    while(l<=r)
    {
        int mid=l+r>>1; poi p1=C[mid];
        if(dcmp(cross(p1-C[1],w-C[1]))>=0)    l=mid+1,ans=mid;
        else    r=mid-1;
    }
    if (n == || years years!)     return  0 ;
    poi p1=C[ans],p2=C[ans+1];
    if(dcmp(cross(p1-w,p2-w))>=0)    return 1;
    return 0;
}
int main ()
{
    int n1=read(),n2=read(),q=read();
    for(int i=1;i<=n1;i++)    p[i].x=read(),p[i].y=read();
    na=gethull(p,A,n1);
    for(int i=1;i<=n2;i++)    p[i].x=-read(),p[i].y=-read();
    nb=gethull(p,B,n2);
    minkowski();
    while(q--)
    {
        poi w; w.x=read(),w.y=read();
        printf("%d\n",check(w));
    }
    return 0;
}
View Code

Note: 1 point if you can find direct triangulation points in the next two polar angle range within which you can 2. As to why I would like to hammer my own dog's head explode it because I cmp wrote dcmp> 1 tune in the convex hull a century xtbl

 

Another questions

N school entrance exam questions

(Title face could not seem to put / px)

 

Our first guess is concluded for odd and even answers are convex, so consider maintaining the parity of four convex positive and negative answers

We do consider how to merge partition

Because the difference is convex so monotonous that we can optimize TwoPointers

Then find complete answers continue to maintain a differential array

(This stuff seemingly also called the partition max convolution / px)

This discovery process is actually in demand and Minkowski

 

My code is written in discussions so long it really fast, but a thief (

//Love and Freedom.
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define inf (ll)(1e18)
#define ll long long
#define N 500010
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
ll f[N][2],d[N][2],tmp[N][2],a[N];
void solve(int l,int r)
{
    if(l==r){f[l][0]=a[l],f[l][1]=a[l]; d[l][0]=a[l],d[l][1]=a[l]; return;}
    int mid=l+r>>1; solve(l,mid); solve(mid+1,r);
    int it1,it2; ll val;
    for(int i=0;i<=r-l+1;i++)    tmp[i][0]=-inf,tmp[i][1]=inf;
    it1=l+1,it2=mid+1; val=d[l][0];
    for(int i=1;i<=r-l+1;i+=2) // odd l odd+ r even-
    {
        tmp[i][0]=max(tmp[i][0],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][0]+d[it1+1][0]>-d[it2][1]-d[it2+1][1]))
            val+=d[it1][0]+d[it1+1][0],it1+=2;
        else
            val-=d[it2][1]+d[it2+1][1],it2+=2;
    }
    it1=l,it2=mid+2,val=d[mid+1][0];// printf("%lld\n",val);
    for(int i=1;i<=r-l+1;i+=2) // odd l even+ r odd+
    {
        tmp[i][0]=max(tmp[i][0],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][0]+d[it1+1][0]>d[it2][0]+d[it2+1][0]))
            val+=d[it1][0]+d[it1+1][0],it1+=2;
        else
            val+=d[it2][0]+d[it2+1][0],it2+=2;
    }
    it1=l+1,it2=mid+2,val=d[l][0]-d[mid+1][1];
    for(int i=2;i<=r-l+1;i+=2) // even l odd+ r odd-
    {
        tmp[i][0]=max(tmp[i][0],val);//printf("%d %d %d %lld\n",i,it1,it2,val);// printf("%lld\n",val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][0]+d[it1+1][0]>-d[it2][1]-d[it2+1][1]))
            val+=d[it1][0]+d[it1+1][0],it1+=2;
        else
            val-=d[it2][1]+d[it2+1][1],it2+=2;
    }
    it1=l,it2=mid+1,val=0;
    for(int i=0;i<=r-l+1;i+=2) // even l even+ r even+
    {
        tmp[i][0]=max(tmp[i][0],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][0]+d[it1+1][0]>d[it2][0]+d[it2+1][0]))
            val+=d[it1][0]+d[it1+1][0],it1+=2;
        else
            val+=d[it2][0]+d[it2+1][0],it2+=2;
    }
    
    it1=l+1,it2=mid+1; val=d[l][1];
    for(int i=1;i<=r-l+1;i+=2) // odd l odd+ r even-
    {
        tmp[i][1]=min(tmp[i][1],val); 
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][1]+d[it1+1][1]<-d[it2][0]-d[it2+1][0]))
            val+=d[it1][1]+d[it1+1][1],it1+=2;
        else
            val-=d[it2][0]+d[it2+1][0],it2+=2;
    }
    it1=l,it2=mid+2,val=d[mid+1][1];
    for(int i=1;i<=r-l+1;i+=2) // odd l even+ r odd+
    {
        tmp[i][1]=min(tmp[i][1],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][1]+d[it1+1][1]<d[it2][1]+d[it2+1][1]))
            val+=d[it1][1]+d[it1+1][1],it1+=2;
        else
            val+=d[it2][1]+d[it2+1][1],it2+=2;
    }
    it1=l+1,it2=mid+2,val=d[l][1]-d[mid+1][0];
    for(int i=2;i<=r-l+1;i+=2) // even l odd+ r odd-
    {
        tmp[i][1]=min(tmp[i][1],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][1]+d[it1+1][1]<-d[it2][0]-d[it2+1][0]))
            val+=d[it1][1]+d[it1+1][1],it1+=2;
        else
            val-=d[it2][0]+d[it2+1][0],it2+=2;
    }
    it1=l,it2=mid+1,val=0;
    for(int i=0;i<=r-l+1;i+=2) // even l even+ r even+
    {
        tmp[i][1]=min(tmp[i][1],val);
        if(it2>r-1 && it1>mid-1)    break;
        if(it2>r-1 || (it1<=mid-1&&d[it1][1]+d[it1+1][1]<d[it2][1]+d[it2+1][1]))
            val+=d[it1][1]+d[it1+1][1],it1+=2;
        else
            val+=d[it2][1]+d[it2+1][1],it2+=2;
    }
    //printf("%d %d\n",l,r);
    for(int i=1;i<=r-l+1;i++)
        f[l+i-1][0]=tmp[i][0],
        f[l+i-1][1]=tmp[i][1];
    //puts("");
    d[l][0]=f[l][0],d[l][1]=f[l][1];
    for(int i=l+1;i<=r;i++)
        d[i][0]=f[i][0]-f[i-1][0],
        d[i][1]=f[i][1]-f[i-1][1];
}
int main ()
{
    int n=read();
    for(int i=1;i<=n;i++)    a[i]=read();
    solve(1,n);
    for(int i=1;i<=n;i++)
        printf("%lld ",f[i][0]);
    return 0;
}
View Code

Guess you like

Origin www.cnblogs.com/hanyuweining/p/11938404.html