Найти количество точек на или внутри треугольника для очень большого количества точек?

Вам дано N точек решетки (Xi, Yi), i = 1, 2, …, N в 2D системе координат.
Вам нужно обработать 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, Yi ≤ 300000 (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("%d\n",count);}
return 0;}

Я получаю SIGSEGV на онлайн-судью, когда дело ввода очень большое
но работает хорошо на небольших тестовых случаях.
Куда я иду не так?

0

Решение

Проверьте первую строку основной функции:

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 из-за слишком большой памяти.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]