2015 ACM多校訓練第二場

在下面網址看效果更佳>_<

http://mlz000.github.io/2015/08/17/2015-ACM%E5%A4%9A%E6%A0%A1%E8%AE%AD%E7%BB%83%E7%AC%AC%E4%BA%8C%E5%9C%BA/

題外話

頹廢了一萬年終於把第二場的題補完了,除了喪病的第一題。。


hdu 5301(1002) Buildings

Solution

水題,仔細討論各種情況即可

Code


hdu 5302(1003) Connect the Graph

Solution

構造題,比賽時沒看,賽後發現挺水的。由於連接黑邊白邊只有0,1,2 三種情況,0我們就不管了。
不妨想考慮白色邊,1,2 的情況我們只需要先構造一個長鏈,解決212 ,然後再把1的搞出來。然後爲了防止重邊,做黑色邊的時候有同樣的方法,連邊時隔着一個點連即可。

Code


hdu 5303(1004) Delicious Apples

Solution

貪心的好題,有兩種情況,一種是都從兩個半邊取,另外一種是從一邊開始取回去後,繞後另外一個半邊取。但是注意到環最多肯定是隻繞一次的,如果繞兩次我們明顯可以只繞一次,然後再走一個半邊。顯然更優。
預處理的時候把所有蘋果按位置排序,dp一下即可。

Code


hdu 5304(1005) Eastest Magical Day Seep Group’s Summer

Solution

好題,刪掉mn 條邊後剩下n 條邊,可以看出是一個樹上有一個環,看到數據範圍很容易想到枚舉環上點的集合。然後剩下的便是生成樹計數問題,可以用Matrix-tree定理解決。
那麼如何求點集爲S 的環的個數呢,考慮狀壓Dp,枚舉環上最小點的標號,令dp[i][j] 爲當前點集爲i ,終點爲j 的方案數,簡單dp即可。最後答案要除以2 ,因爲每個環兩個方向都算了一遍。而且注意到長度爲1的環是不算的。
複雜度O(2n×n3)

Code


hdu 5305(1006) Friends

Solution

水題,隨便搜搜就過了= =

Code


hdu 5306(1007) Gorgeous Sequence

Solution

神題,主要考察複雜度的分析= =然而我並沒怎麼理解QAQ。。。
打了和正常線段樹一樣的標記tag,另外記錄了一個cov標記,表示該節點下多少個葉子節點被控制,還維護了mx,表示最大值。每次修改的時候,不直接修改,先dfs到葉子節點,清一下之前的標記,然後再返回來修改該節點。sum更改時只要增加tag值控制的節點的sum即可。
感覺非常的玄幻= =太神了。。。蒟蒻不太理解QAQ

Code


hdu 5307(1008) He is Flying

Solution

比賽時沒怎麼想,賽後發現並不難。
首先容易想到用s[i] 表示前i 段的和,答案是(ji+1)xs[j]s[i1] ,最後x 的次數爲k 的就是對於長度爲k 的答案。
變化一下形式得j×xs[j](i1)×xs[j]s[i1] ,再拆一下得到j×xs[j]×xs[i1]xs[j]×(i1)×xs[i1]
這樣熟悉FFT的同學馬上就會發現這是個卷積的形式,FFT直接搞就可以了。由於精度問題,可以選擇大質數的NTT,或者兩個int型的NTT再中國剩餘定理合併。實測選取大質數NTT會更快一些。

Code


hdu 5308(1009) I Wanna Become A 24-Point Master

Solution

24點= =水題,就是麻煩。。。
我的做法是分爲n12 ,如果n12 ,那麼顯然可以搞出2×3×4 這種形式,分奇偶不同處理一下即可。比如多的一些數是4 ,那就不停的乘4除以4即可。
n<12 時,手算即可。

Code


hdu 5309(1010) JRY is Fighting

Solution

這題看了鳥神的題解一直沒看懂= =。。最後問了他才搞明白。。感謝鳥神。
很容易想到二分答案,如何驗證是個問題。首先預處理出一個數組rr[i] 表示在第i 秒嗑藥後能挺到第幾秒。然後我們二分答案再驗證,如何驗證是核心。
考慮下面check長度爲x的代碼,建議和輸出答案的nxt 數組一起考慮。
我們將點轉換爲區間考慮,d[i] 表示i 到終點的嗑藥次數,如果d[i]>d[i+1] 表示i 這一時刻要嗑藥,然後我們分了三種情況考慮

  • (1)r[i]>n 表示這個點可以直接到終點,顯然我們可以再這點嗑藥
  • (2)r[i]i<x ,這個點顯然不能嗑藥,因爲間隔<x
  • (3)否則r[i]+1>i+x ,如果最近的間隔到了i+l 這一時刻可以到達最後的終點(d[i+x]>d[r[i]+1] ),顯然我們這第i 時刻可以嗑藥。

同時由於我們要求字典序最小,顯然如果能取前面的就儘量取前面的,這個d 數組挺難理解的,不知道我自己理解的是否透徹QAQ,可以把d 數組看做後面整個區間的一個最值,從後往前推時d 值不降,呈階梯狀,變化時表示可以嗑藥。注意到第一次嗑藥時沒限制的,最後特殊判斷一下即可。

bool check(int x) {
    d[n] = 0;
    for (int i = n - 1; i >= 1; --i) {
        if (r[i] > n)   d[i] = d[i + 1] + 1;
        else if (r[i] - i < x)  d[i] = d[i + 1];
        else    d[i] = d[i + 1] + (d[i + x] > d[r[i] + 1]);
    }
    return d[1] > d[r[0] + 1];
}
void print() {
        for (int i = n - 1; i >= 0; --i) 
            nxt[i] = d[i] > d[i + 1] ? i : nxt[i + 1];
        int top = 0;
        int x = nxt[1];
        while (x) {
            s[top++] = x;
            if (r[x] > n)   break;
            x = nxt[x + ans];
        }
}

Code

完結撒花!
繼續補題!>_<

發佈了86 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章