-1

2D 座標系上の N 個の格子点 (Xi、Yi)、i = 1、2、...、N が与えられます。Q 個のクエリを処理する必要があります。各クエリは "xy d" の形式で与えられます。ABC を A(x+d, y)、B(x, y)、C(x, y+d) に頂点を持つ三角形とする。クエリごとに、三角形 ABC の内側または境界上にある特定の格子点の数を見つける必要があります。入力

入力の最初の行には、スペースで区切られた 2 つの整数 N と Q が含まれます。次の N 行のそれぞれは、格子点の x 座標と y 座標を与える 2 つのスペースで区切られた整数 Xi、Yi を含みます。次に、次の Q 行には、クエリを与える 3 つのスペースで区切られた整数 x、y、d が含まれます。出力

クエリごとに、三角形の内側または境界上にある特定の格子点の数を表す 1 つの整数を線上に出力します。制約

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 を取得しますが、小さなテスト ケースでは問題なく動作します。どこが間違っていますか?

4

1 に答える 1

2

main 関数の最初の行を確認します。

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

ここでは、2 次元配列 X を動的に割り当てています。次の制約を参照してください。

N ≤ 300000 (3 * 10^5)

したがって、プログラムは X[3 *10^5][3 *10^5] を割り当てます。整数の 9*10^10 配列。このサイズの配列は大きすぎてメモリに収まりません。どのプログラミング言語でも、このような大きなメモリを割り当てる/許可することはできません。

次のリンクを参照してください

SIGSEGV は、無効なメモリ参照またはセグメンテーション違反によって引き起こされるエラー (シグナル) です。範囲外の配列要素にアクセスしようとしているか、メモリを使いすぎている可能性があります。

したがって、 メモリが多すぎるため、プログラムはSIGSEGVを生成しました。

于 2013-02-07T21:09:20.297 に答える