首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

HDU 5032 Always Cook Mushroom:離線極角排序 + BIT 解二維平面區域和查詢

     編輯:C++ 入門

問題描述

1000×1000 整數網格,點 (x,y) 權值 = (x+A)(y+B)。Q 次查詢:給定極角 θ(由向量 (a,b) 確定)和半徑 X,求極角 ≤ θ 且 x ≤ X 的所有點權值和。A,B 為常數。

離線處理思路

  1. 將所有網格點 (1..1000, 1..1000) 按極角 atan2(y,x)(或斜率 y/x)排序,存入數組 points。
  2. 每個查詢包含 (X, θ, id),按 θ 排序。
  3. 雙指針掃描:遍歷查詢,將 points 中極角 ≤ 當前查詢 θ 的點依次加入 BIT(按 y 座標為索引,值為權值)。
  4. 查詢 BIT 前綴和 query(X) 即為答案。

BIT 實現

ll bit[1005];
void add(int idx, ll val) { for (; idx<=1000; idx+=idx&-idx) bit[idx]+=val; }
ll sum(int idx) { ll r=0; for(; idx>0; idx-=idx&-idx) r+=bit[idx]; return r; }

完整 C++ 代碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Pt { int x, y; double ang; };
struct Qry { int X, id; double ang; ll ans; };
vector pts;
vector qrs;
ll bit[1005];

int main() {
    // 預處理所有點
    for (int x=1; x<=1000; x++)
        for (int y=1; y<=1000; y++)
            pts.push_back({x, y, atan2(y, x)});
    sort(pts.begin(), pts.end(), [](Pt a, Pt b){ return a.ang < b.ang; });

    int T; scanf("%d", &T);
    for (int cas=1; cas<=T; cas++) {
        int A, B; scanf("%d%d", &A, &B);
        int Q; scanf("%d", &Q);
        qrs.resize(Q);
        for (int i=0; i

關鍵點

  • 極角用 atan2(y,x) 或斜率 y/x 排序,atan2 精度更穩。
  • BIT 索引為 y(1..1000),查詢條件 x ≤ X 轉化為 BIT 前綴和(因掃描時已保證極角 ≤ θ,只需再限制 y ≤ X)。
  • 離線處理將二維條件(極角、x)分解為:掃描極角 + BIT 維護 x 前綴和。
  • 預處理點表一次,多測試用例復用,極大提速。

複雜度

  • 預處理:\( 10^6 \log 10^6 \) 排序(一次)。
  • 每測試用例:排序查詢 \( O(Q \log Q) \),掃描點 + BIT 操作 \( O(10^6 \log 1000 + Q \log 1000) \)。
  • 總時間主導於點掃描,但常數極小,C++ 輕鬆通過。

總結

HDU 5032 是「離線極角排序 + BIT」的教科書級應用。將二維幾何查詢轉化為一維掃描 + 一維數據結構,利用極角單調性與 BIT 前綴和特性,完美解決大規模靜態點集的扇形區域和查詢。此模板廣泛適用於「極角/斜率排序 + 區域聚合」問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved