8.22

POJ 1984 Navigation Nightmare(路徑壓縮並查集)

並查集,給n個點和m條邊,每條邊有方向和長度,再給q個詢問,第i個詢問查詢兩個點之間在Ti時刻時的曼哈頓距離(能連通則輸出曼哈頓距離,否則輸出-1

http://images.cnitblog.com/blog/591194/201401/03134632-ccc7c8865b924d70825412b5a035e58e.jpg

這題還要注意數據可能不是按照時間順序輸入的,要做按時間順序由小到大排序,然後再按原來的順序輸出。還是路徑壓縮的一套不過這次有兩個r[]數組,rx[i]表示i節點到父親節點的x距離,ry[i]同理,輸入m條邊時,

for (i=1;i<=m;i++)

    {

        scanf("%d%d%d %c",&x[i],&y[i],&d,&c);

        switch(c)

        {

            case 'W':dx[i]=-d;dy[i]=0;break;//西

            case 'S':dx[i]=0;dy[i]=-d;break;

            case 'E':dx[i]=d;dy[i]=0;break;

            case 'N':dx[i]=0;dy[i]=d;break;

        }

}

for (i=1;i<=k;i++)

    {

        for (;j<=a[i].idx;j++)

        {

            fx=find(x[j]);fy=find(y[j]);

            fa[fy]=fx;

            rx[fy]=rx[x[j]]-rx[y[j]]-dx[j];//到根節點的距離,fxfy左邊爲負,右邊爲正

            ry[fy]=ry[x[j]]-ry[y[j]]-dy[j];//fxfy上方

爲正,下爲負

        }

        if (find(a[i].x)!=find(a[i].y))

            ans[a[i].n]=-1;

        else

            ans[a[i].n]=abs(rx[a[i].x]-rx[a[i].y])+abs(ry[a[i].x]-ry[a[i].y]);

    }

POJ 2631 Roads in the North(樹的直徑)

求樹上最長的兩個點之間的距離。這裏有一個結論,在圖中,要找到距離最遠的兩點,先隨便從一個點入手bfs,找到距離這個點最遠的點,在從這個點bfs找到距離這點最遠的點,這兩點之間的距離就是這顆樹的直徑。即首先從樹上任意一個點a出發, (BFS)找出到這個點距離最遠的點b. 然後在從b點出發(BFS)找到距離b點最遠的點c. 那麼bc間的距離就是樹的直徑.所以直接進行bfs搜索就行了

poj 1985 Cow Marathon 【樹的直徑】

和上一道題目一樣,裸題。

樹狀數組只能計算A[1]開始的和,A[0]這個元素是不能用的,複雜度O(logn)。執行n次add操作,總時間複雜度O(nlogn)。注意,剛開始c數組要初始全0,然後每讀入一個數A[i]就執行一步add(i, A[i])來進行真正的初始化。

且樹狀數組處理的數組A[n]是從小標1開始的,也即A[0]是一個沒有用的元素。

C數組中的每一個元素都是A數組中的一段連續和。

HDU 1166 敵兵佈陣(簡單樹狀數組)

樹狀數組裸題

UVA1428 Ping pong(樹狀數組)

先別想與樹狀數組有什麼聯繫?先想拿到這個題目怎麼做?很容易想到枚舉誰可以當裁判,但裁判的條件是,假設c是裁判,a,b是對手,則a<=c<=b,即裁判能力值介於比賽者之間,且比賽選手是在裁判住所兩側各挑一個,不能都在同一側,他當裁判時有幾種比賽組織方式。對於第i個裁判,他能組織多少種比賽?

假設a1~a[i-1]有L個能力值比a[i]小的,那麼比a[i]大的i-1-L個

A[i+1]~a[n]有R個能力值比a[i]小的,那麼比a[i]大的有n-i-R個

··················i················

L個小於等於a[i]                      R個小於等於a[i]

i-1-L個比a[i]大                    n-i-R個比a[i]大

顯然,第i個裁判可以組織的比賽場數

L*(n-i-R)+(i-1-L)*R。

問題就轉化成了,對於每個裁判怎麼求其,L,R,這個地方就可以用樹狀數組了。

對每個i,求左邊比他小的數,正着跑一邊,這個數出現了,就在他的位置加1,對於每個數,先求一下比他小的有幾個,再把這個數add進去。

對每個I,求右邊比他小的數,倒着跑一邊,這個輸出現,就在他的位置+1,對於每個數,先求一下比他小的有幾個,再把這個數add進去。

3 4 5 1 1 2爲例

求左邊

C數組

1位置     2位置        3位置      4位置     5位置

  0          0            0           0          0

Sum(3)=0,顯然左邊比3小的沒有

Add(3,1)

   0          0            1           0          0

Sum(4)=1,顯然左邊比4小的有一個

Add(4,1)

   0           0            1           1

Sum(5)=2,顯然左邊比5小的有兩個

Add(5,1)

   0           0             1          1          1]

Sum(1)=0,顯然1左邊小於等於它的沒有

Add(1,1)

   1           0             1           1         1

Sum(1)=1,顯然1左邊小於等於它的有一個

Add(1,1)

   2           0             1           1         1

Sum(2)=2,顯然2左邊小於等於它的有2個

求右邊類似

C數組

1位置     2位置        3位置      4位置     5位置

  0          0            0           0          0

Sum(2)=0;

Add(2,1)

   0         1             0          0         0

Sum(1)=0

Add(1,1)

   1          1            0           0         0

Sum(1)=1

Add(1,1)

   2           1           0           0         0

····

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章