這些天一直在集訓,考了十幾次……
zzy出了一道曼哈頓距離下的最小生成樹,考場上我沒做出來……
嗯……這種題目的問題在於,你沒辦法把每兩個點都建一條邊……
但是因為是曼哈頓距離,所以有一些特殊性質
容易證明,將某個點為原點建立笛卡爾座標系,將座標系分為每45°角為一塊的八個區域
那麼這個點向每個區域只會朝其中的某個點連邊……
為什麼說容易證明,因為我不會證……網上ms有這種證明的說……
貼一下zzy的題解:
所以我們只要求乙個點在其45°角的區域內離他最近的點就行了,而這可以用線段樹或樹狀陣列解決
我們以y軸正半軸往右偏45°角的區域為例:
點j在點i的這個區域要滿足的條件是:
yj-xj>yi-xi
且xj>xi
那麼我們將點以x為第一關鍵字,y為第二關鍵字,排序後倒序插入線段樹
線段樹的線段這一維是離散後的y-x,值是y+x
我們要求的是大於yi-xi的最小的y+x,而xj>xi這個條件已經由插入順序滿足了
這樣我們成功的解決了這個區域的點
而其他區域的點我們可以通過座標變換轉移到這個區域
由於對稱性,我們注意到其實只要求x軸或y軸正半軸所在的四個區域就行了
那麼這個問題就這樣解決了
不過,我沒有找到地方提交這個題目……只是ac了zzy的題
**在此:題目是求最小生成樹上第k大邊,使用了樹狀陣列
//lib
#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
//macro
#define rep(i,a,b) for(int i=a,tt=b;i<=tt;++i)
#define drep(i,a,b) for(int i=a,tt=b;i>=tt;--i)
#define erep(i,e,x) for(int i=x;i;i=e[i].next)
#define irep(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define read() (strtol(ipos,&ipos,10))
#define sqr(x) ((x)*(x))
#define pb push_back
#define ps system("pause");
typedef long long ll;
typedef pairpii;
const int oo=~0u>>1;
const double inf=1e100;
const double eps=1e-6;
string name="brs", in=".in", out=".out";
//var
int n,k,cnt,tot,ans;
int lisan[100008],l[100008];
int limit=1000000008;
struct p
int query(int x)
{ int ret=oo,pos=n+1;
for(int i=x;i<=n;i+=lowbit(i))
if(s[i]
這個程式效率巨低,開o2和不開o2差距達到1倍以上……雖然我覺得這種寫法很優美就是了……
曼哈頓距離最小生成樹
一 前人種樹 部落格 曼哈頓距離最小生成樹與莫隊演算法 部落格 學習總結 最小曼哈頓距離生成樹 二 知識梳理 曼哈頓距離 給定二維平面上的n個點,在兩點之間連邊的代價。即distance p1,p2 x1 x2 y1 y2 曼哈頓距離最小生成樹問題求什麼?求使所有點連通的最小代價。最小生成樹的 環切...
關於曼哈頓距離的最小生成樹 POJ3241
題目位址 題目就是給你n個點 求n個點的曼哈頓距離的最小生成樹 輸出所有邊中第k大的的邊的權重。n個點那麼有有n n 1 條邊如果採用樸素的prim演算法建邊就是o n2 的複雜度,我們來考慮一下曼哈頓距離的特殊性,其實不是所有的邊都需要,在建邊的時候就可以去掉很多多餘的邊。如圖,對於給定的一些點我...
二維曼哈頓距離最小生成樹
原理 每個點在以它為頂點的45 角範圍內,只可能連向距離 曼哈頓距離 它最近的點。證明 以點a為原點,y軸正半軸向x軸正半軸方向偏45 角為例 如圖所示,設 ab ac 所有距離都是曼哈頓距離 a 0,0 b x1,y1 c x2,y2 ab x1 y1 ac x2 y2 bc x2 x1 y2 y...