hihoCoder 1661 陣列區間

2022-09-17 12:48:12 字數 2300 閱讀 7935

給出 $1$ 到 $n$ 的乙個排列($n\le 10^5$),記做 $a_1, a_2, \dots, a_n$ 。(注:原題面表述為:「給定 $n$ 個互不相同且不超過 $n$ 的整數」,並未指明 $a_i$ 是正數,屬描述不確切,實際題意如此。見管理員賽後發的題解)求所有可能的區間中前 $k$ ($k\le \min(n,50)$)大的數之和的總和,對於長度不足 $k$ 的區間則全部累加。(注:前 $k$ 大是指「最大的 $k$ 個」)

這是一道「標準的」區間統計類問題。不難想到思路:考慮 $a_i$ 在多少個區間內能成為前 $k$ 大的數之一。

進一步轉化成:

對每個數 $a_i$,求它 前面/後面 離它最近且比它大的 $k$ 個數的下標。

這個問題把我難住了。看了管理員的題解後,學到正解如下。

按 $a_i$ 從小到大的順序求解。原因在於:若 $a_j < a_i$ 則 $a_j$ 對 $a_i$ 的結果毫無影響,故而按此順序求解,求出 $a_i$ 對應的答案過後便可將 $a_i$ 刪除。不難想到,可以用「雙向鍊錶」來維護原序列;每次向前 $k$ 跳,再向後 $k$ 跳即可。複雜度 $o(nk)$ 。

我並未手寫雙向鍊錶,而是用了std::list。我對std::list的介面不熟悉,這次又到 cppreference.com 上溫習了一下。

這道題用std::list要注意的點有:

std::list::iterator屬於bidirectional iterator,僅支援++--運算,不能加/減乙個整數也不能兩個 iterator 做差。

要注意區別std::list::iteratorstd::list::reverse_iterator這兩個型別。二者貌似是可以互相做型別轉換的。例如

std::lista;

std::::iterator it=a.begin();

std::::reverse_iterator rit = a.rend();

std::::reverse_iterator rit2(it);

assert(rit == rit2);

需要注意的是,當 iterator 轉成 reverse_iterator 時,會向前移動一次,即返回的 reverse_iterator object 指向的是原 iterator object 所指向的前一位置。

另外,在宣告 reverse_iterator 時若要做此型別轉換則只能以(){}的方式賦初始值不能以=的方式(至少 g++ 如此)。

#include using namespace std;

lista;

const int n =1e5+5;

list::iterator iter[n];

int pre[51];

int post[51];

int main()

long long ans =0;

for(int i=1; i<=n; i++);

// cout << "x: "<< *riter << '\n';

while(1)

// cout << *riter<<'\n';

pre[c1] = *riter;

if(c1==k) break;

++c1;

}int c2=1;

auto tmp = iter[i];

while(1)

post[c2]=*tmp;

if(c2==k) break;

++c2;

}assert(c2 <= k);

int pos = *iter[i];

// for(int i=1; i<=c1; i++)

// cout << pre[i] << ' ';

// cout << '\n';

// for(int i=1; i<=c2; i++)

// cout << post[i] << ' ';

// cout << '\n';

pre[0] = pos;

for(int j=1; j<=c1; j++)

a.erase(iter[i]);

}cout << ans << '\n';

return 0;

}

hihocoder 字尾陣列

時間限制 5000ms 單點時限 1000ms 記憶體限制 256mb 描述小hi平時的一大興趣愛好就是演奏鋼琴。我們知道乙個 旋律被表示為長度為 n 的數構成的數列。小hi在練習過很多曲子以後發現很多作品自身包含一樣的旋律。旋律是一段連續的數列,相似的旋律在原數列可重疊。比如在1 2 3 2 3 ...

B 迴圈陣列 HihoCoder 1704

hihocoder 1704 給定包含n個整數的陣列a1,a2,an,你可以選擇任意乙個ai,將ai旋轉到陣列第一項,即將陣列變成 ai,ai 1,ai 2,an,a1,a2,ai 1 現在小hi希望旋轉之後的陣列滿足 對於任意k 1 i n 前k項的和都是正數。例如對於a 3,5,2,2,3,0 ...

HihoCoder 1523 陣列重排2

給定乙個1 n的排列a1,a2,an,每次操作小hi可以選擇乙個數,把它放到陣列的最左邊。請計算小hi最少進行幾次操作就能使得新陣列是遞增排列的。input 第一行包含乙個整數n。第二行包含n個兩兩不同整數a1,a2,an。1 ai n 對於60 的資料 1 n 20 對於100 的資料 1 n 1...