牛客國慶集訓派對Day6

牛客國慶集訓派對Day6

以下是我個人題解,出題人題解附帶在最後

A.Birthday

費用流裸題,只要注意到1+3+5+...+2k1=k21+3+5+...+2k-1 = k^2即可已做這道題了.
其他的地方連邊都很方便.每一個區域向匯點連很多條容量爲11的邊,但費用分別是1,3,5,...,2k11,3,5,...,2k-1.
最後跑最小費用最大流即可.

B.Board

注意到我們先對每一行進行操作,每一行各行減去它們行內的最小值.然後每一列減去它們逐列的最小值.可以保證,這樣操作一輪以後,所有點的數都變成了00.
初始把問好處設爲0,這樣操作一遍以後,指定格子處乘以1-1就是答案.

C. Circle

注意到(x,x+1)(x,x+1)必然互質,因此直接輸出nn.

D.土龍弟弟

unsolved.

E.Growth

s[x][y]s[x][y]表示所有aix,biya_i\le x,b_i\le yziz_i之和.
dp[x][y]dp[x][y]表示從第00天開始,到第x+yx+y天的屬性分配滿足a:x,b:ya:x,b:y所獲得的最大值,

轉移方程

dp[x][y]+ps[x][y]dp[p+x][y]dp[x][y] + p*s[x][y] \rightarrow dp[p+x][y]

dp[x][y]+qs[x][y]dp[x][y+q]dp[x][y] + q*s[x][y] \rightarrow dp[x][y+q]

ss數組直接用二維前綴和預處理即可.

dpdp轉移的時候採用bfsbfs順序轉移即可.

F.kindom

很容易得到方程

dp[n]=dp[x1]+x1+dp[x2]+x2+...+dp[xm]dp[n] = dp[x_1] + x_1 + dp[x_2] + x_2 +... + dp[x_m]

其中xixj,i<jx_i\le x_j,i < j時.且滿足xi=n1\sum x_i = n-1.

dp[n]=dp[x1]+dp[x2]+...+dp[xm]+(n1xm)dp[n] = dp[x_1] + dp[x_2] + ... + dp[x_m] + (n-1-x_m)

轉移時枚舉xmx_m的大小,那麼求dp[x1]+dp[x2]+...+dp[xm1]dp[x_1] + dp[x_2] + ... + dp[x_{m-1}]的最大值.

由於dp[x]x2dp[x] \ge x-2,因此dp[x]dp[x]的增長速率必然不低於線性,因此當x1,...,xm1x_1,...,x_{m-1}儘可能越大越好.

故方程變爲:

dp[n]=max1xmn1{n1xmxmdp[xm]+dp[(n1xm)%xm]+dp[xm]}dp[n] = max_{1\le x_m \le n-1}\{\lfloor \frac{n-1-x_m}{x_m} \rfloor * dp[x_m] + dp[(n-1-x_m)\%x_m] + dp[x_m]\}

時間複雜度O(n2)O(n^2)

G.Matrix

unsolved.

H.Mountain

最大值乘2.

I.清明夢超能力者黃YY

算法一

涉及:樹鏈剖分,掃描線

在一個線段的情況下,我們可以把一個染色區間拆成左端點處增加事件,右端點處刪除事件.
維護一顆權值線段樹.
這樣,端點從小到大掃描時,遇到增加事件就在線段樹指定位置+1,遇到刪除事件就在線段樹指定位置-1.

那麼要回答一個點的答案只需要掃到這個點的時候,在權值線段樹裏二分kk大值即可.

這個搬到了樹上,我們照樣可以使用掃描線的方法來做.

對於每一個染色區間,將其剖到樹鏈上去,可以剖出最多log(n)log(n)個小區間.

這些小區間的深度較小的端點加入增加事件,深度較大的端點加入刪除事件.

然後對整棵樹按照dfndfn序列從小到大依次掃描即可,注意掃描的過程中也要維護一顆權值線段樹.

算法二

涉及:dfs,權值線段樹合併

對於每個詢問u,vu,v,應該在uu處加入增加事件,在vv處加入增加事件,在lca(u,v)lca(u,v)處加入刪除事件,在faz[lca(u,v)]faz[lca(u,v)]處加入刪除事件.因此每個詢問會產生44個事件.

我們採用dfs的順序,每個點維護一顆權值線段樹,然後後序遍歷到達一個節點時候,先將它所有兒子的線段樹進行合併,合併完成後,將該點涉及到的增加或刪除事件執行到線段樹上,此時,該點的權值線段樹維護的就是橫跨這個節點的所有染色區間.

然後在權值線段樹上進行kk大詢問即可得到該點的答案.

J.最短路

先建樹,樹建完後多餘100100條邊,每條邊取左端點,得到100100個端點,從這些點出發跑bfsbfs,可以得到從這些點到任意一點的最短路.對於每個詢問,枚舉這100100個點ss,求dis[s][u]+dis[s][v]dis[s][u] + dis[s][v]的最小值即爲答案.

總的時間複雜度:O(100k+100n)O(100k + 100n)

K.排序

unsolved.

附錄

以下是出題人題解:

birthday:
思路:考慮費用流時把每個part拆成n個點,選擇第i個點的代表爲放置i塊蛋糕和(i - 1)塊蛋糕的時間差,這個時間差是遞增的,因此在費用流的過程中必定會從小到大選擇
具體建圖:左邊n個點代表n個蛋糕,右邊m * n個點代表m個part,每個part拆成n個點。源點向每個左邊的點連一條流量1費用0的邊,每個右邊的點向匯點連一條流量1費用0的編。每個蛋糕向可以放的兩個part的所有點連邊,連向第i個點的費用爲i^2 - (i - 1)^2,流量爲1。這樣求最小費用流既爲答案。

board:
把格子N染色,第i行第j列格子的顏色爲(i + j) % N。那麼每次操作時,必定是N種不同的顏色都有一格被操作到,因此最後任何顏色格子的和必定是相等的。因此只需要記錄每種顏色格子的和,並算出缺失格子的顏色C,用其餘顏色的和減去顏色C的和即可

Circle:
因爲(i,i+1)=1且(1,n)=1,所以把1…n依次放進一個環,就可以啦。答案爲n。

Growth:
把獎勵的x拿出來從小到大排序,得到x1,x2,…,xn。
把獎勵的y拿出來從小到大排序,得到y1,y2,…,yn。
用v[i][j]表示a值到達xi,b值達到yi時接下來每天可以得到的獎勵。
v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j]
其中t[i][j]爲滿足x=i,y=j的獎勵的總和。
用f[i][j]表示a值達到xi,b值達到yj時已經拿到的獎勵的最大值。
f[i][j] + (x[i + 1] - x[i] - 1) * t[i][j] + t[i + 1][j] -> f[i + 1][j]
f[i][j] + (y[j + 1] - y[j] - 1) * t[i][j] + t[i][j + 1] -> f[i][j + 1]
最後統計一下答案就可以了。

kingdom:
f[i]代表i個點時的答案,g[i][j]代表若干顆樹加起來,size和爲i,每棵樹size<=j時,這些樹的代價和最大是多少
從1到n枚舉i,在i固定時枚舉心腹的影響力大小更新f[i],然後用類似揹包的思路更新g[i][1]~g[i][i]
複雜度O(N^2)

Matrix:
w個格子的重心的座標爲(∑xiwi / ∑wi, ∑yiwi / ∑wi)。
那麼其實我們只要維護∑xiwi,∑yiwi,∑wi就可以了。
假設我們現在有一個頂點爲(x, y)的三角形,我們想要推到頂點爲(x, y+1)的三角形,觀察兩者之間的差異,會發現在推過去的過程中,其實就是刪去了一個斜條,又加入了一個斜條。
同理,從(x, y)到(x+1, y)其實只是刪去了兩個斜條,加上了底上的橫條,而這些關鍵的值都是可以通過前綴和的方法維護。

Mountain:
考慮山中最高的一座,最優操作一定是從第一座山的左下角開始不停地往上爬,然後從最高的山不停地往下爬爬到最後一座山的右下角。
所以答案爲最高山的高度*2。

清明夢:
首先每條路徑從LCA處分開可以拆成兩條鏈
假設鏈A->B執行了第i次染色操作,假設A是B的祖先,那麼我們在B點加入一個"插入i"的事件,在A的父親點加入一個"刪除i"的事件
然後dfs整顆樹求解,每個點維護一個線段樹。處理一個點時先合併所有兒子的線段樹,然後再處理這個點上的事件,得到線段樹之後詢問第K大值既可得到答案。
複雜度分析:
Node* merge(Node* a, Node* b) {
if (a == NULL) return b;
if (b == NULL) return a;
a->sum += b->sum;
a->child[0] = merge(a->child[0], b->child[0]);
a->child[1] = merge(a->child[1], b->child[1]);
return a;
}
考慮以上的線段樹合併,每次合併會減少一個區間。而在事件點插入、刪除的時候會產生至多log個區間,因此複雜度爲O(NLogN)

最短路:本題十分直接。我們不斷地把度數爲1的點刪掉,把度數爲2的點收縮,最後會得到一個圖,和原圖的點數與邊數之差相同,且新圖中每個點的度數都至少是3。這就是說我們會得到一個200個點300條邊以內的圖。新圖可以用Floyd算法預處理所有點對之間最短路。詢問時,將詢問轉化到新圖上即可。轉化時需要注意細節。

排序:設m是a和b的差的lowbit。我們先假設m是1,即a和b的奇偶性不同。這時通過適當的構造,我們可以用常數步交換任意兩個奇偶互異的數字的位置。交換奇偶相同的數只要借一個和它們奇偶不同的數即可。如此我們便可交換任意兩個數,即此時沒有無解。下面考慮m大於1。我們稱一個數字x的低位爲(x&(m-1)),高位爲x減去它的低位。我們發現數組的低位是無法利用交換魔法的,只能用到加法和異或。也就是說,我們必須用加法和異或排好數組的低位。排好低位後,我們按照低位將所有數字分爲若干組,每組內(和之前m爲1的情況類似)是沒有無解的。現在問題只剩如何用加法和異或排好低位。可以發現,a[0],…,a[m-1]的低位和a[m],…,a[2m-1]的低位必須完全一致且均爲0到m-1的一個排列,否則它們無法同時通過加法和異或排好。同理a[2m],…,a[3m-1]的低位也必須一致。所以,我們只要用加法和異或排好a[0],…,a[m-1]即可。這其實是本題的n=m且沒有交換魔法的版本(因爲現在超過m-1的加法和異或是沒用的)。在這個版本下,從升序排列只能生成(m/2)(2**(m/2))種不同的排列。這些排列可以用遞歸法構造:m=2時用一次加法即可(後面會解釋爲什麼用加法不用異或)。m更大時,我們發現連續使用加1和異或1可以達到奇數都加2,偶數都不變的效果。這個操作實際相當於只考慮奇數且不考慮個位情況下的加1操作。這就可以提取所有奇數做遞歸,將所有奇數排列成任意的m/2時的可能排列。同理,先異或1再加1起到的是偶數加2奇數不變的效果。我們相似地遞歸偶數部分。注意到,遞歸一側時,異或操作是會影響另一側的。奇數和偶數兩側的異或操作的異或和必須相同(因爲整體考慮,異或操作其實是同時作用在奇數和偶數上的!),除了個位和最高位。(除了個位是因爲我們根本不考慮個位,個位有值的異或操作只用在異或1的時候了。除了最高位是因爲最高位異或可以用奇數+2操作模擬出來。)這樣可以得到的排列數最多爲(m/2)(2**(m/2)),同時滿足條件的排列都可以用遞歸法構造出來。

土龍弟弟:下面會有一些定義。出此題是期望比賽的時候大家憑感覺得到結論,不證明。
首先題目問的是在torus上扣若干個洞,所得曲面上的閉環的同倫等價類。(定義:torus:就是我們定義的地圖,形似甜甜圈。閉環:就是說土龍弟弟一天走的路徑。因爲會回來所以叫閉環。同倫等價類:就是一個土龍弟弟的路線可能會變換。凡是可能屬於同一個土龍弟弟的兩條路線就是相互同倫的。題目問的就是最少能分成多少組使得組內相互同倫。)我們把扣掉的洞用線連起來,使得線之間不相交且按照線將曲面分割成若干簡單的部分。(簡單的部分:就是這一部分是你在紙上隨便畫個不自交的閉環得到的東西。簡單是因爲這一個區域中所有的閉環都同倫,因爲可以縮小到很小再移動到一起。)分割區域這一步需要小構造一下。大體思路就是每一行都畫一條橫的線,這線實際會被洞分割成多條線。然後有些區域是個環(即從左邊走到最右邊再向右回到最左邊),即並非簡單區域。這些區域再畫一條豎線。
這樣分割後,一個閉環就可以用依次穿過的線的編號組成的字符串來表示(除了記錄哪條線,方向也有用。並且由於是環,字符串也是循環的。)然後消去相鄰相反括號(即連續的正穿和反穿同一條線的部分。因爲每個區域都是簡單的,所以連續正穿和反穿中間的部分可以不斷收縮直到不穿過這條線,所以消去後所得的曲線和之前是同倫的。)最後爲了判斷循環串相等要用最小表示法。證明:我們要證的是同倫當且僅當消去相鄰相反括號後的序列循環相等。 假設a經過消括號得到(不能再消的)b,顯然a和b是同倫的,因爲每一步都同倫。假設a’消括號得到b’。如果b和b’循環相等,a和b同倫。這就證明了一半。反過來,對一個曲線做同倫變換時,只能產生或消除相鄰的相反括號。所以如果b和b’不等,他們又都沒有相鄰相反括號可以消去,它們就不可能通過產生和消除相鄰相反括號相互轉換,即b和b’不同倫,即a和a’不可能同倫。
最後注意沒有洞是特殊情況。題面裏除去了這種情況。其實torus上扣若干洞後的基本羣總是free group,但是沒扣洞時的基本羣是Z^2(平面整數格點加法羣)。

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