JOISC 2020 題解(不會題答)


「JOISC 2020 Day1」建築裝飾 4(dp+構造)


一個做法是設\(f[i][j][0/1]\)表示一共選了\(j\)個A了,第\(i\)個選了A還是B,是否可行。

注意到可行的\(j\)其實是一個區間,證明歸納易得。

於是設\(f[i][0/1]\)表示可行的區間,直接dp即可。

我的做法是,假設先不管n個A的限制,從左往右掃一遍,每次選盡量小的,保證有解先。

考慮有些位置的選擇可以改變,x改變了,x+1可能要改變,可能不要改變。

如果x改變了,x+1必須跟着改變,x->x+1連一條邊,不難發現有若干條鏈。

每一條鏈可以選一個后綴,那么用不等式加法原理算一算就好了。

代碼:https://loj.ac/submission/769869

「JOISC 2020 Day1」漢堡肉(2-sat+數據結構優化建圖)


神題。。。

先說隨機亂搞法。

每次先隨機k個矩形,然后把其它矩形加入,每次選面積減小比最小的一個。

隨便hack,但是它能過數據。

正經做法:

考慮算出\(maxl,minr,maxd,minu\)

先考慮橫坐標。

假設\(maxl>minr\),否則橫坐標放在\([maxl,minr]\)的任意一個位置都行。

\(x=minr\)這條直線的左邊,至少要放一個點,因為\(minr\)是一個矩形的右邊界,這個矩形在\(x=minr\)的左邊。

又因為這是最左的右邊界,所以不如把一個點就放在\(x=minr\) 上,這樣還能覆蓋右邊的一些矩形。

同理,對\(maxl,maxd,minu\)可以得到類似的結論。

於是得到結論:
\(k\)個點的坐標中,\(maxl,minr,maxd,minu\)都至少出現了一次。

\(k<=3\)時,有鴿巢原理,至少有一個點的兩維坐標都是\(maxl,minr,maxd,minu\)中的一個。

枚舉這個點,把它覆蓋的矩形去掉,遞歸到\(k-1\)的情況。

\(k=4\)時,先討論以上的情況,最后的一種情況就是\(maxl,minr,maxd,minu\)圍成的矩形A上,每一條邊有一個點。

現在考慮其它要被覆蓋的矩形B,如果一個矩形B經過了A的三條邊,那一定有一條邊是完全覆蓋,所以矩形B一定會被覆蓋不考慮。

剩下的情況就是:

1.B覆蓋A的一個角。

2.B覆蓋A的兩條對邊。

3.B覆蓋A的一條邊。

4.B和A無交

如果出現4說明每條邊放一個(不放交點)無解。

三種情況皆可用一個2-sat模型來說明:

對於一條邊上的一個區間:[x,y],建立兩個點代表它選or不選,

當同一邊上兩個區間不交時,則只能選一個。

1,2相當於兩個區間至少選一個

3相當於這個區間必須選。

用數據結構(線段樹)優化區間不交的連邊可以做到\(O(n~log~n)\)

代碼(隨機):https://loj.ac/submission/769928

「JOISC 2020 Day1」掃除(線段樹分治+平衡樹)


對於一開始y隨x遞增而不遞增的部分分,可以發現每次修改的都是一段區間。

用線段樹(平衡樹)維護,每次先二分出修改的區間,然后區間賦值即可。

對於沒有4操作的部分分,發現,對於被移動過至少一次點,它們之間滿足y隨x遞增而不遞增。

所以先對每個點求出第一次移動的時間(二維排序問題),或者平衡樹在線維護什么時候移動。

在點第一次移動時,丟入一棵維護已經移動過點的平衡樹,那棵平衡樹做前面說的操作。

有4操作時,發現主要是因為新加入的點沒有經過前面修改的洗禮,所以不滿足那個性質了。

對於每個詢問,相當於求一個點經過一個區間的操作后的結果。

利用線段樹分治,把這個區間分成線段樹上的log個區間。

這樣的話,對於線段樹上的一個區間,上面的詢問都要經過這個區間的修改,就可以當沒有4操作那么做了。

時間復雜度:\(O(n~log^2~n)\)

代碼:https://loj.ac/submission/772057

「JOISC 2020 Day2」變色龍之戀(交互題,二分)


如果詢問兩兩點(x,y),答案不為2當且僅當(x,y)滿足下面條件之一:

1.l[x]=y

2.l[y]=x

3.c[x]=c[y]

先暴力詢問把邊都找出來。

如果一個點x度數為1,那么相鄰的點就是同顏色的點。

否則,它的度數為3,設相鄰點為y1,y2,y3

詢問(x,y1,y2),(x,y1,y3),(x,y2,y3)

發現不包含\(l[x]\)的那組答案是1,這樣就求出\(l[x]\)了,其它組答案是2。

那么再掃一遍就知道每個點同顏色的點是哪個了。

這個只用詢問前兩組就知道結果了。

所以,如果能找出邊,那么\(4n\)次詢問就能求出答案。

考慮告訴你每個點屬於二分圖哪一部分的那檔數據:

對於一個點x,設S為對面的一個點集,當\(query\{x,S\}≠|S|+1\)時,說明x和S有邊。

於是,枚舉二分圖左半的每個點,在右邊二分就好了,這樣\(3~log~n\)次一個點。

全部數據不告訴我們二分圖的構成,我們想去求,然而做不到。

考慮一個一個點加入。

現在加入點x,求它與之前點的邊(之前點之間的邊已經知道)。

由於之前點的邊已經知道,可以對它們染色,分成兩個集合,集合內部沒有邊。

這個集合可能不是原二分圖的一邊上的點,但是沒有關系,因為它們之間沒有邊就可以二分x與它們的邊。

詢問數\(\le 3n~log~n+2n+4n\)

\(2n\)是試探性詢問帶來的常數。

Code:https://loj.ac/submission/772404

「JOISC 2020 Day2」有趣的 Joitter 交友(並查集+STL+啟發式合並):


做的那天有點亂,沒一開始想清楚應該維護哪些東西,所以沒調出來。

首先,如果x和y之間互相右邊,那么把它們縮成一個並查集里,因為其他點到這個並查集的一個點有邊相當於到這個並查集的所有點都有邊(反過來不成立)。

考慮現在加入一條邊x->y:

先取y為y的並查集祖先。

1.如果x這個點到y並查集已經有邊了,那么這條邊就不用加入了。

所以維護\(set~s1[x]\)表示x這個點能到哪些並查集。

2.如果y並查集到x的並查集有邊,那么x,y應該merge。

求並查集之間邊的條數應記錄一個\(map<int,int>~bz[N]\)

在merge的時候,比如是把\(x\)並查集並入\(y\)並查集。

首先需要修改一下\(x,y\)之間的\(bz\),順便處理一下答案的影響。

然后,對於\(x\in s1[z]\),應該改成\(y\in s1[z]\),為了找到這些\(z\),應該記錄\(set~s2[x]\)表示並查集\(x\)的入點。

在處理\(s1[z]\)時,順便改一下\(z\)\(\{x,y\}\)對答案的影響,同時如果\(y->z所屬並查集\)本來有邊,應遞歸merge。

\(x,y\)的merge應用啟發式合並,即\(bz[x].size+s2[x].size<=bz[y].size+s2[y].size\)

有一個問題,就是\(s2[y]\)中由\(x\)來的邊不好刪除,為了刪除,可能需要額外再記錄一下東西,但是我用了lazy刪除。

即先不刪,放在那里,到枚舉\(z\in s2[y]\)時,如果y,z在一個並查集,那么就忽略,為了統計答案需要記錄數組表示這樣的邊數。

反正這就是個細節討論題。

代碼:https://loj.ac/submission/772330

「JOISC 2020 Day2」遺跡(計數dp)


一道很agc的dp題。

先考慮如何快速求最終剩下的點:

for(int i = 2 * n; i >= 1; i --) {
	int x = cho[i];
	while(x > 0 && !us[x]) x --;
	us[x] = 1;
}

意思就是從大到小枚舉每個點,看看每個點會停在哪兒。

有了這個可以dp,順序肯定是從大到小。

問題是現在相當於us有很多段1,不可能記錄每一段,事實上我們就記錄第一段連着us[1]的長度,之后的段后面再填。

\(f[i][j]\)表示選擇了\(>=i\)的,\(us[1..j]=1,us[j+1]=0\)的方案數。

考慮由\(f[i+1][...]->f[i][...]\)

\(i\)不需要保留:

那么它會放在\(j\)個中的一個,問題是這個系數也不好求,因為不知道哪些地方可以放。

此時更改一下題目的定義:每個地方放的兩個有順序關系,這樣答案最后\(÷2^n\)

這樣的定義下,一共有\(j-outA\)個空位(outA是已經不保留的個數),系數就是這個。

若i需要保留:

1.它會停在\(>j+1\)的位置,那這個之后到那里時再考慮。

2.它停在\(j+1\),那么再枚舉一個\(k\),表示\(us[j+2..j+k]=1,us[j+k+1]=0\)

系數就是\((k+1)*C_{inA-j}^{k-1}*g[k-1]\)(inA是已經保留的個數)

\(g[n]\)表示n個數,加入后使\(us[1..n]=1\)的方案數。

\(g[n]\)可以通過上面那個dp類似的方法自我更新出來,但有一種更簡單的方法:

\(cnt[j]=\sum[cho[i]=j]\),

\(g[n]=\forall i<=n (\sum_{j=1}^i{cnt[j]})\le i\)的方案數

所以設\(dp[i][j]\)表示前i個位置,\(cnt\)的和\(=j\)的方案數。

\(dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*2*j+dp[i-1][j-2]*j*(j-1)\)

\(g[n]=dp[n][n]\)

代碼:https://loj.ac/submission/772714

  

「JOISC 2020 Day3」星座 3(笛卡爾樹+線段樹合並或樹形dp)


對於一個區間\([l_i,r_i]\),找到最高點\(a[x]\)

這個區間只能有一個\(>=a[x]\)的點。

暴力就是先建出笛卡爾樹:

\(f[i][j]\)表示\([l_i,r_i]\)里選的最高點是\(j\)的最大和。

轉移有:

x這里選一個點j0,左區間選一個j1,右區間選一個j2。

可以一個接一個合並,復雜度\(O(n^2)\)

用線段樹合並優化一下就\(O(n~log~n)\)

另一種常數更小的做法:

考慮把笛卡爾樹建成一個樹形關系。

如果在x這里選了一個y,選y就相當於覆蓋了x到x的一個祖先\(z(a[z]<=y且a[fa[z]]>y)\)

可以倍增求出\(z\)

問題變為一棵樹上有若干祖先后代鏈,選出不相交的若干鏈,使權值和最大。

經典問題(不是祖先后代鏈也能做),只需要dfs序+樹狀數組實時維護一個點到根的dp值的和就差不多了。

代碼(線段樹合並):https://loj.ac/submission/772405

​  

「JOISC 2020 Day3」收獲(基環內向樹+線段樹合並):


考慮對每一個點求出\(fa[i]\)表示i取了一個果子后,下一個取這個果子的是誰。

因為每個點一條出邊,所以是個基環內向樹。

再處理一下每個果子第一次被誰吃,然后把每個果子的時間改為被第一個人吃的時間+到樹根的時間。

用個線段樹合並再查詢一下得到樹上的答案。

接着考慮環上的答案。

先破環為鏈,記一個前綴和數組\(s[x]\)表示從\(x\)走到1的答案,設環長是\(len\)

\(x,y\)都是環上的點:

假設\(y\)子樹里的一個果子到\(y\)的時間是\(T1\),而\(x\)處有一個詢問\(T2\)

\(v1=T2-s[x]-[x>y]*len\)

\(v2=T1-s[y]\)

那么貢獻就是:\([v1>=v2]*(\lfloor {(v1-v2)\over len}\rfloor+1)\)

看似需要三維偏序,因為多了個\([x>y]*len\),但由於這里的貢獻是\(len\),除了分母之后也就是1,可以討論一下變成二維偏序,細節略,我這里用了三棵線段樹。

Code:https://loj.ac/problem/3278

【JOISC 2020】迷路的貓(通信題,bfs序、構造):


考慮k>=3時,如果一棵樹,那么對每條邊i->fa[i],染上dep[i]%3.

這樣的話,詢問時,會得到x和(x+1)%3有值,走x就好了。

如果多了些其它邊,考慮建出圖的bfs序的生成樹(一直想dfs序沒想出來),那么多的邊兩個點也一定深度相鄰,同樣的標號方法即可。

k=2、B=6時。

深度為1的點只有一個方向,走就好了。

深度為3的點x,染色保證x->fa[x]和z->fa[z]=x的顏色不一樣,同時在走的過程中記錄上一次的邊的顏色,這樣,只出現一次的顏色就是要走的方向。

剩下的問題一開始在鏈上就要判斷方向。

考慮構造一個循環串S,使得S順時針看長度為x的子串和逆時針看長度為x的子串都不一樣。

這樣,只要先走x步,看看是順時針出現在S中還是逆時針,就可以判斷方向,在判斷了方向后,不走來的邊即可。

如果走x步就會最多多花2x步,所以2x<=B。

S、x可以爆搜,發現不管怎么樣找不到x<=3的解,能找到一個x=5的解,這樣可以拿到部分分。

事實上,走x步,算上起點的另一條邊和終點的另一條邊,我們一共知道了5條邊的信息,

所以只用3步就好了。

特別注意染色是要同時滿足兩個條件。

代碼:http://uoj.ac/submission/389005

「JOISC 2020 Day4」首都城市(數據結構優化建圖+tarjan 或 點分治+bfs)


做法1:

如果顏色i的虛樹上有顏色j的點,i->j連一條邊。

建出圖后縮強聯通分量,出度為0且點數最小的分量就是答案。

用倍增或者樹鏈剖分優化這個建圖即可做到\(O(n~log~n)\)

做法2:

考慮點分治,每次強制選分治中心,求選它的答案。

選它的答案可以用bfs實現,具體為:

一開始加入分治重心的顏色到隊列里,每次取隊列頭的顏色,枚舉這個顏色的所有點x,開始跳父親,把路過的顏色加入隊列,直到跳到一個已經在虛樹上的點。

注意是只在分治子樹內bfs,因為如果出去了,就說明要經過更高的分治重心,那么在那個時候就統計答案了。

這個復雜度也是\(O(n~log~n)\),常數更小。

代碼(樹鏈剖分優化建圖):https://loj.ac/submission/774428

「JOISC 2020 Day4」治療計划(數據結構優化建圖+dij)


發現找不到狀態,不如從左往右依次確定(注意時間無序,只考慮區間上的變化):

\(f[i]\)表示\(1-r[i]\)都搞定了的最小代價。

注意這個dp里,時間是無序的,我們只考慮的是能不能

\(f[i]\)能轉移到\(f[j]\)當且僅當:

\(r[i]-l[j]+1\ge|t[i]-t[j]|\)

討論\(t[i],t[j]\)的大小關系,用線段樹優化建圖跑dij。

時間復雜度:\(O(n~log^2~n)\)

代碼:https://loj.ac/submission/774430


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM