1. 程式人生 > >JZ模擬賽 8.9

JZ模擬賽 8.9

矩陣 clas 後綴 class 相同 由於 bubuko put 為什麽

B組:

T1:

農夫約的假期

Description:

在某國有一個叫農夫約的人,他養了很多羊,其中有兩頭名叫mm和hh,他們的歌聲十分好聽,被當地人稱為“魔音”······
農夫約也有自己的假期呀!他要去海邊度假,然而mm和hh不能離開他。沒辦法,他只好把他們兩個帶上。
到了海邊,農夫約把他的羊放在一個(n*n)的矩陣(有n*n個方格)裏。mm和hh十分好動,他們要走到m(m<=n*n)個地方,第i個地方的坐標為(x[i](行),y[i](列)),每到一個地方他們會高歌一曲,制造q[i]點魔音值,因為他們的魔音十分獨特,他們的聲音只能橫著或豎著傳播。每傳播一格,魔音值會增加1。(傳播的格子數取最小的)接下來農夫約要住酒店。為了方便照顧小羊們,他選的酒店的坐標要在矩陣內。但小羊們的魔音讓他十分頭疼。他想求出魔音值最小的地方。
他還要享受他的假期,所以他把這個任務交給你了,加油(^_^)。

概括:給定一些二維坐標點,求一個點,使得這些點到這個點的曼哈頓距離最小。

Output

第一行一個整數表示魔音值最小是多少。
接下來一行兩個正整數zb1和zb2,表示魔音值最小的地方的坐標(如果有多個答案,輸出橫坐標最小的情況下,縱坐標最小的)。

Solution:

考慮縱坐標,一定是縱坐標中位數。

反證:如果不是,那麽比中位數大的點mid+1都會+1,mid個點-1,不論上下位移,都不優。

橫坐標同理。

由於橫坐標最小,縱坐標最小,所以如果偶數,選擇小的一個。

之後,乘一下z,然後加一下qi的和。這兩部分都是定值。

(話說JZOJ標程忘了乘z,結果無人AC~~)

T2:

小x遊世界樹

Description:

小x得到了一個(不可靠的)小道消息,傳說中的神島阿瓦隆在格陵蘭海的某處,據說那裏埋藏著亞瑟王的寶藏,這引起了小x的好奇,但當他想前往阿瓦隆時發現那裏只有聖誕節時才能到達,然而現在已經春天了,不甘心的他將自己的目的地改成了世界樹,他耗費了大量的時間,終於將自己傳送到了世界樹下。世界樹是一棵非常巨大的樹,它有著許許多多的枝條以及節點,每個節點上都有一個平臺。好不容易來到傳說中的世界樹下,小x當然要爬上去看看風景。小x每經過一條邊都會耗費體力值。然而世界樹之主想給他弄(gáo)些(dǐan)麻(shì)煩(qíng),於是他在每條邊上都設了一個魔法陣,當小x踏上那條邊時會被傳送回根節點,魔法陣只生效一次。這豈不是要累死小x?幸運的是,每個平臺上都有無數個加速器,這些加速器可以讓小x在當前節點所連的邊上耗費的體力值減少,不同平臺的加速器性能不一定相同,但同一個平臺的加速器性能絕對相同。世界樹之主給了小x一次“換根”的機會,他可以將世界樹的任何一個節點變為根,但所有的邊都不能改變。小x想問你,將根換為哪個節點能使小x爬到世界樹上的每個節點耗費的體力值和最少。默認編號為1的點為初始根。

(題目太麻煩)

給定一棵樹:你要選擇一個根,使得到每個點的距離之和最小。邊權根據題意,從兩個端點出發,可能加速器不一樣,權值不同。

Solution:

裸的二次掃描換根法。

首先dfs一遍,處理子樹大小,dis值之和。

再dfs一遍,從當前欽定根到一個兒子點的時候,這條邊影響了dis總和值。子樹外的點dis總和加上邊權,子樹點的dis總和減去邊權。註意,邊方向不同。

O(n)處理一下就好了。

T3:

觀察

Description:

出題人給出一顆以1為根的樹,一開始每個節點都是一顆棋子,一面白一面黑,白色的面朝上
接下來就q次操作,操作分兩種
0操作 將一個顆棋子翻轉
1操作 詢問一顆棋子與所有面朝上為黑色的棋子lca最深的那個(lca)的編號

Solution:

非常非常沒有思路是不是???

有一個不顯而易見的結論:

如果詢問求一個x,和它產生答案的黑點一定是dfs序中,x後繼黑點和x前驅黑點。

為什麽呢?

dfs有一個性質,一定會遍歷整個子樹之後,才會繼續搜索。

所以,

1.如果前驅\後繼在x子樹裏,顯然答案就是x,沒錯。

2.如果前驅是x的某個祖先y,說明,要麽x到y的路徑上其他子樹裏,不會有黑色節點,要麽有,就是後繼了。(否則不滿足dfs序先掃完一個子樹的性質了)

所以,要麽是前驅,要麽是後繼。

兩個分別lca,取深度較深的點即可。

怎麽求dfs序裏面,x前驅後繼呢?

1.set,按照dfs序排序,直接upper,lower

2.線段樹,區間以編號為下標(dfs序:1~n)維護這個區間內,黑點的個數。

每次找x,就是從[1~x-1]找最大的黑點,劃分logn區間後,優先找右子樹,有黑點就進,否則進左子樹。到了葉子就返回。

(我們也可以擴展一下,求k個點的lca,就是dfs序最小的一個,和dfs序最大的一個求lca)

修改直接改。

復雜度:m2logn

A組:

T1:

餐館

Description:

K妹的胡椒粉大賣,這辣味讓食客們感到刺激,許多餐館也買這位K妹的賬。有N家餐館,有N-1條道路,這N家餐館能相互到達。K妹從1號餐館開始。每一個單位時間,K妹可以在所在餐館賣完盡量多的胡椒粉,或者移動到有道路直接相連的隔壁餐館。第i家餐館最多需要A[i]瓶胡椒粉。K妹有M個單位的時間,問她最多能賣多少胡椒粉。

N,M<=500

Solution:

沒什麽可以說的。直接樹形背包。因為可能走一下子樹,再返回根。

所以:f[i][j][0/1]表示,從i出發往子樹裏面走,花j時間,不返回/返回的最優收益。

dp就好了。

T2:

Description:

技術分享圖片

技術分享圖片

Solution:

暴力分挺高的。20分暴力,50分P是質數,前綴積,再處理逆元一下就可以了。nlogn

P不是質數:

由於k是給定的。

不妨每k個作為一個塊。處理每個點到所在塊末尾的後綴積,和前綴積。

對於恰好在k裏,直接隨便輸出。

否則,兩個端點,l後綴積,r前綴積再乘一下就好了。

直接乘,避免了逆元。

T3:

隨機

Description:

技術分享圖片

技術分享圖片

Solution:

暴力n^2logn

發現,其實,設取min的操作答案是A,長度是m,區間為l,r

如果l不變,r更大,m變大,A可能變小。

但是要再取max,所以,當m>A的時候,再往後移r就沒有意義了。因為max只能更大。

之後,就後移l,m變小,A可能變大。

而A>m的時候,可以往後移,m雖然大了,但是A可能更小。

所以,每個點進一次,出一次,2n

註意時刻保證m>=2

但是,怎麽向區間加入點,刪除點的時候,快速更新A呢?

如果只是ai取min,直接一個multiset搞定。

但是這是一個差值。

所以,再開一個multiset2,記錄multiset1,就是存數的set,大小相鄰兩個數的差值。

顯然,set2裏面必然有一個是min{|si-sj|}

插入一個點ax,從set1找到後繼ay+1,前驅ay,把ay+1-ay的值從set2裏面刪掉一個。

把ax-ay,ay+1-ax放進set2,ax放進set1。

刪除一個點ax,找前驅後繼。

刪除ax-ay,ay+1-ax,放進ay+1-ay, set1刪除ax(倒著做一遍)

每次取set2.begin()就是min

JZ模擬賽 8.9