n2) 暴力自然不用說, 用手中石子去檢查地上石子是否撿的起來, 若撿的起來就撿, 直到沒有石子可以撿為止
正解:分塊
對於這種有多個屬性的若干物品需要比較大小來檢查合法不合法的問題,
可以嘗試這個方法:
1. 整個陣列排序
2. 分塊
3. 塊內排序
4. 暴力
於是先將地上石子按距離排序
分成nn
個塊, 每個塊內按質量排序
此時手中就有了處理過後的整個陣列,每個塊的包含的極值 (由於對每個小塊排序亂了距離的單調性, 質量單調性得到保證, 於是極值只需要記距離即可)
每次拿手中的石子將所有能撿到的石子全部撿起 (即加入佇列),
將手中石子彈出佇列, 取出隊首繼續進行上述操作, 直到隊列為空
接下來詳細敘述石頭怎麼撿
先找到第乙個 最小距離 小於該 手中石頭 吸引半徑的塊, 對於這個塊前面的所有塊, 其中符合條件的石子可能就在這些塊中
對每個可能的塊遍歷(可以在上述找的過程中實行), 同樣找到第乙個不符合條件的石子t
t, 這個塊中符合條件的石子即 t
t 前面所有的石子, 將這些石子從塊內刪除, 加入佇列
對於刪除操作, 可以記每個塊內左右端點為 l,r
l,r, 刪除時直接將 l
l 移動到 t
t 的位置上即可(刪除過程可以邊走邊刪)
為什麼這段**會爆掉?
int
&l = b[j]
.l, r = b[j]
.r;while
(l <= r &&
(ft.r >= a[l]
.d && ft.p >= a[l]
.m)) q.
push
(a[l ++])
;
而這是正確的 ↓
↓
if
(b[j]
.min_d > ft.r)
break
;//~
int&l = b[j]
.l, r = b[j]
.r;if
(b[j]
.max_d <= ft.r)
while
(l <= r && a[l]
.m <= ft.p)
else
這是因為在將小區塊排序後, 小區塊內的距離並不是單調遞增, 只有當這個塊內的所有石子距離一定符合條件時, 才可以直接挪動區塊的 l
l , 即 l++
l++ (完全扔掉石子 alal)
#include
#define reg register
intread()
while
(isdigit
(c)) s = s*
10+ c-
'0', c =
getchar()
;return s * flag;
}typedef
long
long ll;
const
int maxn =
350005
;int n;
int used[maxn]
;struct stone
} a[maxn]
;struct block b[maxn]
;bool
cmp_d
(stone a, stone b)
bool
cmp_m
(stone a, stone b)
intmain()
int size =
sqrt
(n), cnt =0;
std::
sort
(a+1
, a+n+
1, cmp_d)
;for
(reg int i =
1; i <= n; i +
= size)
int ans =0;
std::queue q; q.
push
(a[0])
;while
(!q.
empty()
)else}}
printf
("%d\n"
, ans-1)
;return0;
}
分塊 CH Round 46 磁力塊
給定一些有座標的磁力塊,當距離滿足吸引距離且重量滿足吸引重量時可吸走該磁力塊,然後可以在新的磁力塊上擴充套件,也可以用原來的磁力塊,問最多能獲取幾個磁力塊 我會平衡樹!滾!用平衡樹等樹形資料結構維護這些資料是很麻煩的,所以我們可以用分塊 因為該解滿足最優性,所以我們可以直接用寬搜擴充套件,中間利用分...
CH 46A 磁力塊 (分塊)
描述 在一片廣袤無垠的原野上,散落著n塊磁石。每個磁石的性質可以用乙個五元組 x,y,m,p,r 描述,其中x,y表示其座標,m是磁石的質量,p是磁力,r是吸引半徑。若磁石a與磁石b的距離不大於磁石a的吸引半徑,並且磁石b的質量不大於磁石a的磁力,那麼a可以吸引b。小取酒帶著一塊自己的磁石l來到了這...
AcWing 250 磁力快(分塊)
題目傳送門 在一片廣袤無垠的原野上,散落著n塊磁石。每個磁石的性質可以用乙個五元組 x,y,m,p,r 描述,其中x,y表示其座標,m是磁石的質量,p是磁力,r是吸引半徑。若磁石a與磁石b的距離不大於磁石a的吸引半徑,並且磁石b的質量不大於磁石a的磁力,那麼a可以吸引b。小取酒帶著一塊自己的磁石l來...