AcWing 109 天才ACM 倍增 歸併

2021-09-29 09:02:17 字數 1304 閱讀 5898

給定乙個整數 mm,對於任意乙個整數集合 ss,定義「校驗值」如下:

從集合 ss 中取出 mm 對數(即 2∗m2∗m 個數,不能重複使用集合中的數,如果 ss 中的整數不夠 mm 對,則取到不能取為止),使得「每對數的差的平方」之和最大,這個最大值就稱為集合 ss 的「校驗值」。

現在給定乙個長度為 nn 的數列 aa 以及乙個整數 tt。

我們要把 aa 分成若干段,使得每一段的「校驗值」都不超過 tt。

求最少需要分成幾段。

輸入格式

第一行輸入整數 kk,代表有 kk 組測試資料。

對於每組測試資料,第一行包含三個整數 n,m,tn,m,t 。

第二行包含 nn 個整數,表示數列a1,a2…ana1,a2…an。

輸出格式

對於每組測試資料,輸出其答案,每個答案佔一行。

資料範圍

1≤k≤121≤k≤12,

1≤n,m≤5000001≤n,m≤500000,

0≤t≤10180≤t≤1018,

0≤ai≤220

思路:首先計算的話肯定是需要每次貪心的取最大最小然後計算,但在考慮區間的時候列舉顯然是不行的,所以我們需要考慮倍增來寫,每次判斷能否擴充套件。由於取最大最小需要有序,我們每次儲存之前的左區間,然後對右區間進行排序,利用歸併的思想將有序的左右區間合成乙個有序區間,然後就可以進行判斷了。

#includeusing namespace std;

typedef long long ll;

const int maxn = 5e5 + 10;

const ll linf = 0x3f3f3f3f3f3f3f3f;

ll a[maxn], b[maxn], v[maxn];

int n, m, k;

ll t;

void merge(int l, int mid ,int r)

while(i <= mid) b[++k] = a[i++];

while(j <= r) b[++k] = a[j++];

}bool check(int l, int mid, int r) // 判斷區間是否可擴充套件

if(ret <= t)

return false;

}int main()

else if(r + len <= n && check(l, r, r + len))

else len >>= 1;

}if(r == n) ++tot;

printf("%d\n", tot);

}return 0;

}

AcWing 109 天才ACM 倍增

題目鏈結 這道題最基本的想法就是一次尋找每個區間,對於每個區間,用二分來判定其最大長度。每次check的時候,對區間排序,不斷取出不大於m對最大值與最小值求值即可。然後你就喜提tle了,笑如果用倍增來代替二分的話能過,不過其實倍增最壞複雜度和二分一樣,應該是資料沒有刻意來卡倍增。下面先給出倍增的 c...

唯一天才挽救不了AC公尺蘭沒落

在幾天前,義大利各大 還在盛讚卡卡是新一代的 球王 是本屆歐洲金球獎的有力競爭者,但緊跟著ac公尺蘭就輸球了,擁有天才球員卡卡,但不代表擁有勝利,畢竟足球是11個人的比賽,乙個卡卡,無法挽救落難的ac公尺蘭。僅僅是擁有乙個巨星的球隊是無法成功的,否則當年擁有羅納爾迪尼奧的巴黎聖日耳曼就不會一無所獲了...

SDOI2017 天才黑客

我們不妨思考一下,兩個串的 lcp 的長度在 trie 樹上是什麼?對應點的 lca 的深度。然後就可以想到把邊看成點,然後把邊與邊之間連邊,點權看成這條邊經過所需要的時間。但是這樣子連邊是 o m 2 的,不夠優秀。我們需要進一步優化。考慮兩個點之間的 lcp 可以用什麼來代替?sa 裡面的 he...