這題的訣竅在於我們需要找到區間內最大值的同時保證剩下的元素能被選全,保證m位密碼能被填滿,區間最大值可以用線段樹維護,這就需要我們維護每次選擇的區間,每一次選擇的區間左端點一定要在上一次選擇出來的元素右方開始,右端點與選擇的次數有關,第一次在第n-m+1位,每一次右端點++即可保證剩餘元素能被選擇最終填滿m位。
我構造了乙個對映ys[x][k],來表示數字x的第k次出現的位置,用陣列cnt[ ]輔助記錄和查詢。查詢時我通過while(ys[ans][cnt[ans]] < head) cnt[ans]++;
來找到在區間內的第乙個出現的最大值的位置。那麼下一次的區間左端點也找到了。以此類推,m次o(logn)的查詢即可結束,而且不需要更新修改的線段樹,總體看下來不難。
具體見**:
#include#define maxn 200005
#define maxm 30000005
#define for(a, b, c) for(int a=b; a<=c; a++)
#define hrdg 1000000007
#define inf 2147483647
#define llinf 9223372036854775807
#define ll long long
#define pi acos(-1.0)
#define ls p<<1
#define rs p<<1|1
using namespace std;
int n, m;
int tr[maxn<<1], a[maxn], ys[20][maxn], cnt[20];
char ch;
void pushup(int p) //維護區間最大值的無修改線段樹
void build(int p, int l, int r)
int mid = (l+r)>>1;
build(ls, l, mid);
build(rs, mid+1, r);
pushup(p);
}int query(int nl, int nr, int l, int r, int p)
int main()
//for(i, 1, n) printf("%d ", a[i]); cout<=10) printf("%c", ans-10+'a');
else printf("%d", ans);
}printf("\n");
}return 0;
}
動態規劃專題 解題報告 D
我們先來想想n2 怎麼做,兩個n2 迴圈乙個求以i結尾的最長上公升子串行,另乙個逆序求一遍,然後列舉i,以i為中間點的長度,迴圈更新結果就有了。是不是很簡單,恭喜你tle。想都不用想必t好嗎?沒有個nlogn演算法怎麼在1e6的資料範圍面前找場子?nlo gn nlogn nlog n做法 我們其實...
動態規劃專題 解題報告 A
乙個經典的貨郎擔問題,加上17的範圍限制各種明示狀態壓縮,用二進位制來表示走過哪幾個城市,我們可以開乙個二維陣列dp i j 表示走過了i的城市,最後在j城市停留的距離。預處理一遍每個城市間的距離,算出dis i j 到dp i j 的狀態可以由 1 1 j k 轉移過來,比較距離儲存最優值就行,然...
資料結構專題 解題報告 J
原題洛谷p1484種樹,又撿到一題做過的,lucky。所謂用堆來解決問題,從來就是乙個詞,貪心,堆的使用是否成功取決於你貪心的策略,而貪心一般來說處理起全域性最優是有難度的,本題引入了乙個小有名氣的高階貪心策略,反悔貪心。通過讀題,我們發現貪心有乙個尷尬之處在於,你如果選擇了此刻的最大值i,那麼在選...