1. 程式人生 > >8 November in 614

8 November in 614

其他 美食 不可 clas main 努力 方案 mes 都得

我開始看心靈雞湯了……

每當在書中讀及那些卑微的努力,都覺得感動且受震撼。也許每個人在發出屬於自己的光芒之前,都經歷了無數的煎熬,漫長的黑夜,無盡的孤獨,甚至不斷的嘲諷和否定,但好在那些踮腳的少年,最後都得到了自己想要的一切。

– 某乎

學習信息競賽對我來說,是一份美妙而充實的身心體驗。隨著一份份代碼的 AC,雀躍的心靈是決不同於其他方面的。文化課的學習生活對我是一種美食的享受,而信息競賽則更像是一次海天盛宴,讓人充滿前進和追求遠方的動力與勇氣。學習算法是快樂的,因為人本不是為使自己更加疲憊而制造工具的,而是簡化工序,使用各種工具讓自己的生活更加簡單便捷。算法競賽是追求化繁為簡的,是追求高效和正確的,這也正是對待生活的良好態度。幾年下來,隨著知識和閱歷的增加,生活也變得更加充滿意義,對時間的把握能力更強了,這是信息競賽帶給我的人生財富。願我在這條路上走得再遠一些,以更好的姿態追求無盡的前方。

今明兩天再總結總結,總結經驗和教訓,把簡單題再紮實一下。不要好高騖遠了,畢竟我學了不少復雜的知識 NOIP 都用不上。(除了模擬退火真貪心啊……)

Contest

A. ssoj2997 刪除(removal)

開始給你 \(N\) 個元素的數組(下標從 1 開始),數組裏的數是 \(1,2,3,…,N\),然後執行 \(D\) 次刪除操作。每次刪除操作給一個區間 \([lo, hi]\),要求刪除下標位置從 \(lo\)\(hi\) 的數,數組裏的數據個數會減少 \(hi-lo+1\) 個。

例如,\(N=8\),第 1 次刪除操作區間是 \([3,4]\),結果為 “\(1,2,5,6,7,8\)

”;第 2 次刪除操作區間是 \([4,5]\),結果為 “\(1,2,5,8\)”。

最後,輸出第 \(M\) 位的數字是什麽。如果剩余的數不夠 \(M\) 個,輸出 \(-1\)

\(1\le M\le N\le 2\times10^9,1\le D\le 50\)

顯然,正向做題不可行,因為操作區間太大。

考慮逆向。對於最後問的第 \(M\) 個數,它前面後面有不少數已被刪去,不過後面的數對答案沒有貢獻,前面的刪除區間不可能覆蓋到 \(M\)(想一想,為什麽?)。

每一次 \(M\) 前面的區間被刪除,\(M\) 的位置相當於向前移動。所以逆向把 \(M\) 前的區間還原回去就可以了。

#include <cstdio>
 
int T, n, m, d, l[53], r[53];
 
int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &d);
        for (int i=1; i<=d; ++i) scanf("%d-%d", &l[i], &r[i]);
        for (int i=d; i; --i) if (l[i]<=m) m+=r[i]-l[i]+1;
        printf("%d\n", m>n?-1:m);
    }
    return 0;
}

B. ssoj2998 jyt 的崇拜者(sequence)

\(n\) 個元素的整數序列 \(A\),要求修改成單調不減的序列 \(B\),代價 \(\max\{|A_i-B_i|,1≤i≤n\}\)。求最小代價。

之前做過,保證 \(B_i\) 一定大於等於 \(A_i\) 即可。

#include <cstdio>
#include <algorithm>
using namespace std;
 
int n, A, B, ans;
 
int main() {
    scanf("%d", &n);
    for (int i=1; i<=n; ++i) scanf("%d", &A),
        B=max(B, A), ans=max(ans, (B-A+1)>>1);
    printf("%d\n", ans);
    return 0;
}

考場上為什麽 WA 了呢?!!!考場上想太多了!

是啊,水題就不要多想,要相信直覺!

C. ssoj2984 螞蟻 ants

Zkp 從小喜歡觀察生物。這一天,他發現臺階上有 \(n\) 只螞蟻排成一排。臺階可以視為長度無限的數軸,第 \(i\) 只螞蟻的位置為 \(p_i\),有的朝左走有的朝右走。每只螞蟻每秒鐘都可以走 1 個長度單位,當兩只螞蟻面對著相遇的時候,他們會立即調轉方向,以原來的速度向新方向繼續前進。現在 zkp 想知道 \(T\) 秒過後,每只螞蟻將會移動到哪裏。

這個是藍書P9(UVa 10881)上的內容。怎能不 A?

#include <cstdio>
#include <algorithm>
using namespace std;
 
int n, T;
 
struct node {int x, d, id; } G[200005];
 
bool cmp1(const node& a, const node& b) {return a.x < b.x || a.x==b.x && a.d<b.d; }
bool cmp2(const node& a, const node& b) {return a.id < b.id; }
 
int main() {
    scanf("%d%d", &n, &T);
    for (int i=1; i<=n; ++i) scanf("%d%d", &G[i].x, &G[i].d),
        G[i].id=i, G[i+n].x=G[i].x+(G[i].d?T:-T), G[i+n].d=G[i].d;
    sort(G+n+1, G+(n<<1)+1, cmp1);
    sort(G+1, G+n+1, cmp1); for (int i=1; i<=n; ++i) G[i].x=i;
    sort(G+1, G+n+1, cmp2);
    for (int i=1; i<=n; ++i) printf("%d ", G[G[i].x+n].x);
    return 0;
}

D. ssoj3149 饑餓的狐貍

到你的寵物狐貍的晚餐時間啦!他的晚餐包含 \(N\) 塊餅幹,第 \(i\) 塊餅幹的溫度是 \(T_i\) 攝氏度。同時,在晚餐中還包含了一大盤 \(W\) 攝氏度的水。

在喝了一口水之後,你的狐貍開始吃飯了。每當他吃一塊餅幹時,這塊餅幹的美味度為當前餅幹與吃 / 喝的前一樣食物(包括餅幹和水)溫度的差的絕對值。它可以在任意時間喝水(保證水喝不完),或按任意順序吃餅幹。

最後狐貍獲得的美味值為它吃下的每塊餅幹的美味度之和。請求出狐貍獲得的最小和最大的美味值。

要得到最小美味值,一種可行的方案是,狐貍先喝水,然後吃第一塊餅幹,再吃第三塊餅幹,接著喝水,最後吃下第二塊餅幹,這樣做,它所感受到的溫度分別為 \(20,18,18,20,25\) 攝氏度,總的美味度為 \(2+0+5=7\)

要得到最大美味值,一種可行的方案是,狐貍先喝水,然後按順序吃餅 \(2+7+7=16\)

$1≤N≤10^5,0≤T_i,W≤10^9 $。

最大值理解了,最小值呢?

#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
 
int n, w; ll d[100003], anl, anh1, anh2;
 
int main() {
    scanf("%d%d", &n, &w);
    for (int i=1; i<=n; ++i) scanf("%lld", &d[i]);
    sort(d+1, d+n+1);
    anl=max(0ll, w-d[1])+max(0ll, d[n]-w);
    ll las=w, l=1ll, r=n;
    for (int i=1; i<=n; ++i) {
        if (i&1) anh1+=max(labs(d[l]-w), labs(d[l]-las)), las=d[l++];
        else anh1+=max(labs(d[r]-w), labs(d[r]-las)), las=d[r--];
    }
    las=w, l=1ll, r=n;
    for (int i=1; i<=n; ++i) {
        if (i&1) anh2+=max(labs(d[r]-w), labs(d[r]-las)), las=d[r--];
        else anh2+=max(labs(d[l]-w), labs(d[l]-las)), las=d[l++];
    }
    printf("%lld %lld\n", anl, max(anh1, anh2));
    return 0;   
}

8 November in 614