鏈結
題意描述
給定乙個h×
w 的網格圖,m個互不相交(定義相交為:∃a
∈rec
a,a∈
recb
且 ∃a
∈rec
a,a∉
recb
)的矩形,n個點對。
當兩點可以不經過矩形相互到達時,稱這個點對合法。
求合法的點對數。
題解
最初的想法就是連線合法邊,對於乙個點dfs一遍,對可以到達的點用並查集維護為乙個集合,這個做法複雜度大概o(hw),姿勢正確的話有60分。
我們可以發現乙個性質。由於矩形互不相交,則:
如果兩個點屬於的最小的矩形相同,則兩個點一定可以連通。
且易證其為充要條件。
於是我們就可以算出兩個點的最小包含矩形,並判斷它們是否相等即可。
這個做法時間複雜度為o(nm)。雖然常數優化了不少,**難度也瞬間下降為普及組第一題,但依然只有60分。
在真正的賽場上,除了想到正解,想到一中易於實現的做法也是乙個成功。採用相對容易的演算法,時間還是風險都有所下降。
這個演算法的瓶頸在計算最小矩形的時間,每做一次都要花費o(m)的時間,一看就很有優化的空間!我們如何用更優秀的時間算出每個點所屬的矩形呢?
最小矩形作為乙個集合元素,不易於代數的描述和記錄。我們嘗試改變表示方法,這就要求我們找出屬於同乙個最小矩形的點的通性,即乙個條件p,作為兩個點屬於同乙個最小矩形的充要條件。
如果給每乙個矩形隨機乙個編號,對包含其的所有矩形的編號以某種方法求乙個雜湊值,不就可以唯一的表示這些點了嗎?
想法很好!接著我們就可以開始優化了。
優化o(m)時間的很常用的做法就是記字首和。然而,一維的字首和是對於一一維的線而言的。對於二維的平面,我們需要對其分治,這也決定了它無法達到一維o(1)效率的轉移,而需要o(log_n)。
這個時候我們遇到了難以逾越的障礙,因為我們很難確定乙個排序的方法,自然也就無法分治秋字首和。
我們發現,「包含」是個不易表示的概念。有沒有辦法用其他方式表示這個概念呢?
對於綠點,屬於矩形p1,在其左上角所包含的區域裡面,有p1的點奇數個,p2、p3的點偶數個。
對於粉點,屬於矩形p1、p2,在其左上角包含p1、p2的點奇數個,p3的點偶數個。
規律很明顯,也易證明。
看到奇偶性我們很容易想到異或操作的性質。我們對於每乙個矩形的四個點隨機乙個雜湊值,就可以表示每乙個,對乙個要求的點的左上方位置的所有端點取乙個異或和作為雜湊值,就可以很大概率唯一的表示此點和此點所屬點集的位置關係了。
我們就是希望將乙個個複雜的矩形轉化乙個個簡單的點,化整為零,使其易於操作,因為我們要乙個排序的方法。而我們知道,對於點的排序是很容易的。
具體的分治方法是先對其x座標進行排序,再對其進行分治。考慮分治[l,r]為[l,mid]和[mid+1,r],已經分治完了左邊,對於屬於右邊的每乙個要求的點,要把左邊y小於等於它的點全部取計入它的雜湊值(此時左邊經過原來對x的排序已經可以保證x都小於要求的這個點的x了)。
可以證明,迭代log_n次後,所有範圍內的點都可以被計入它的雜湊值(想想為什麼)。
最後比較一下這個點對的雜湊值。
時間複雜度分析
最初的對x排序由於x不超過107
,桶排序可以o(h)過。分治迭代llog_n層,每層詢問要對n個點貢獻雜湊值,每次貢獻需要求y恰好小於等於這個點y值的點,可以用乙個log_n二分找出。
總時間複雜度o(
h+nl
og2n
) 。
問題就完美的解決了。
(最後乙個點奇怪wa掉的**)
#include
#include
#define r register
#define max_rand 1000010
using namespace std;
struct nda[3000010],c[3000010];
struct ansb[500010];
struct ordf[3000010];
int n,m,h,w;
int at=0,ft=0;
int st[10000010];
intread()
bool cmp(const nd &a1,const nd &a2)
if(a[l].y>lim)return
0; return a[r].y
<=lim?r:l;
}void merge_sort(r int l,r int r)
r int i,j,k,mid=(l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
for(i=mid+1;i<=r;++i)if(a[i].num!=0)
i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
while(j<=r)c[k++]=a[j++];
while(i<=mid)c[k++]=a[i++];
a[l]=c[l],a[l].s=(a[l].num==0?a[l].hash:0);
for(i=l+1;i<=r;++i)
a[i]=c[i],a[i].s=a[i-1].s^((a[i].num==0)?a[i].hash:0);
}int main()
; c[++at]=(nd);
b[i].p1=b[i].p2=-1;
}for(i=1;i<=m;++i)
;c[++at]=(nd);
c[++at]=(nd);
c[++at]=(nd);
}for(i=1;i<=at;++i)
f[++ft]=(ord),st[c[i].x]=ft;
for(at=0,i=0;i<=10000002;++i)
for(e=st[i];e!=0;e=f[e].nex)
a[++at]=c[f[e].key];
merge_sort(1,at);
for(i=1;i<=at;++i)
if(a[i].num!=0)
(b[a[i].num].p1==-1)?(b[a[i].num].p1=a[i].hash):(b[a[i].num].p2=a[i].hash);
for(i=1;i<=n;++i)
return
0;}
yzoj P1122 階乘 題解
t組資料,給出n,求出n!最右邊非零的數。對於30 的資料,n 30,t 10。對於全部的資料,n 10 2009,t 30。一道數學題 解析n!10x 最後一位數字即是結果。10x進行拆分,變成5 x 2x。怎麼除以5x呢,好辦,乘的時候含有5的倍數的一項全部不乘進去,再遞迴此過程。即 1 2 3...
YZOJ P1232 異或遊戲
題型特徵 維護區間資訊,需要對每個左端點重新構造情況,不可通過字首和差分。一般方法 對左端點排序,處理每乙個含有這個左端點的區間詢問,並移動左端點。保證了左端點最多經歷le n 次修改。題意描述 t組詢問,每組詢問要求區間 l r 中出現次數為偶數的數的異或和。t 2 105 n 5 105 正解a...
BZOJ3290 花神的數論題
3209 花神的數論題 time limit 10 sec memory limit 128 mb description 背景 眾所周知,花神多年來憑藉無邊的神力狂虐各大 oj oi cf tc 當然也包括 ch 啦。描述 話說花神這天又來講課了。課後照例有超級難的神題啦 我等蒟蒻又遭殃了。花神的...