对于大量的点,求三角形上或三角形内部的点数

Find the number of points on or inside a triangle for very large number of points?

本文关键字:三角形 内部 于大量      更新时间:2023-10-16

给你N个格点(Xi,Yi),i=1,2。。。,N。您必须处理Q个查询,每个查询都将以"x y d"的形式给出。设ABC是顶点在A(x+d,y)、B(x,y)和C(x,y+d)的三角形。对于每个查询,您必须找到有多少给定的格点位于三角形ABC的边界内或边界上。输入

输入的第一行包含两个空格分隔的整数N和Q。以下N条线中的每一条都有两个空间分隔的整数Xi,Yi给出了格点的x和y坐标。然后下面的Q行包含三个空间稀疏整数x,y,d,给出一个查询。输出

对于每个查询,在一条线上输出一个整数,该整数表示位于三角形内部或边界上的给定格点的数量。限制

1≤N≤300000(3*105)
1≤Q≤200000(2*105)
1≤Xi,易≤30万(3*105)
1≤x,y,d≤300000(3*105)

样品

Input 1: 
5 3  
1 3  
1 5  
3 6  
4 4  
2 6
1 5 3    
1 5 4
1 1 1
Output 1:
3
3
0
Input 2:
2 2
1 5
3 7
2 5 6
2 3 4
Output 2:
1
0

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int sizer[300000]={0};//sizer[i] tells the number of points having i as the abscissa
int cmp(const void *a,const void *b)
{
    return *(int *)a-*(int *)b;
}
int main()
{
    int **X=(int **)malloc(300000*sizeof(int));//each pointer points to an array of ints
    for(int i=0;i<300000;i++)
    X[i]=NULL;
    int N,Q;
    int x,y,d;
    scanf("%d %d",&N,&Q);
    scanf("%d %d",&x,&y);
    sizer[x-1]++;
    for(int i=1;i<=N;i++)
    {
        scanf("%d %d",&x,&y);
        sizer[x-1]++;
        X[x-1]=(int *)realloc(X[x-1],sizer[x-1]*sizeof(int));
        X[x-1][sizer[x-1]-1]=y;}
        for(int i=0;i<300000;i++)
        {
         if(X[i]!=NULL)
         qsort(X[i],sizer[i],sizeof(int),cmp);}//sorts all the ordinates
         for(int i=1;i<=Q;i++)//query loop
         {
          scanf("%d %d %d",&x,&y,&d);
          int count=0;
          for(int j=x;j<=x+d;j++)//this loop works for each row from x to x+d
          {
           if(X[j-1]==NULL)//no points on X=j line
              continue;
           else if(X[j-1][sizer[j-1]-1]<y)//the largest ordinate point on X=j line is <y ie                below the triangle
              continue;
           else if(X[j-1][0]+j>x+y+d)//the smallest ordinate point on X=j line is above the triangle
               continue;  
         int k=0;
        for(;X[j-1][k]<y&&k<sizer[j-1];k++);//k is the position from where counting of points begins.moving along the X=j line and counting the points
        int v=k;
        for(;X[j-1][v]+j<=x+y+d&&v<sizer[j-1];v++);
        count=count+v-k;}
        printf("%dn",count);}
        return 0;}

当输入案例很大时,我会从在线法官那里得到一个SIGSEGV但在小型测试用例上运行良好。我哪里错了?

检查主函数的第一行:

int **X=(int **)malloc(300000*sizeof(int));

在这里,您动态地分配一个二维数组X。现在,请参阅以下约束:

N ≤ 300000 (3 * 10^5)

因此,您的程序将分配X[3*10^5][3*10^5],即9*10^10的整数数组。此大小的数组太大,无法放入内存。在任何编程语言中,都不能分配/允许这么大的内存。

参考以下链接

SIGSEGV是由无效内存引用或分段故障引起的错误(信号)。您可能试图越界访问数组元素,或者试图使用过多内存

因此,由于内存太多,您的程序生成了SIGSEGV