第十一屆藍橋杯校內賽:選節目(線段樹解法)

選節目

小明要組織一臺晚會,總共準備了 n 個節目。然後晚會的時間有限,他只能最終選擇其中的 m 個節目。這 n 個節目是按照小明設想的順序給定的,順序不能改變。
小明發現,觀衆對於晚上的喜歡程度與前幾個節目的好看程度有非常大的關係,他希望選出的第一個節目儘可能好看,在此前提下希望第二個節目儘可能好看,依次類推。
小明給每個節目定義了一個好看值,請你幫助小明選擇出 m 個節目,滿足他的要求。

輸入格式

輸入的第一行包含兩個整數 n, m ,表示節目的數量和要選擇的數量。
第二行包含 n 個整數,依次爲每個節目的好看值。

輸出格式

輸出一行包含 m 個整數,爲選出的節目的好看值。

樣例輸入
5 3
3 1 2 5 4
樣例輸出
3 5 4
樣例說明

選擇了第1, 4, 5個節目。
評測用例規模與約定
對於 30% 的評測用例,1 <= n <= 20;
對於 60% 的評測用例,1 <= n <= 100;
對於所有評測用例,1 <= n <= 100000,0 <= 節目的好看值 <= 100000。

線段樹區間返回區間最值及下標
  • 線段樹維護一個pair(存儲下標與最大值)
  • 初始查詢區間爲(1,n-m+1)(ql=1,qr=n-m+1)
  • 查詢區間ql根據查詢範圍移動,qr++
#include <bits/stdc++.h>
using namespace std;
static const int maxn = 1e5 + 5;
static const int mod = 10000;
typedef long long ll;
int a[maxn];
struct node
{
    int id;
    int left,right;
    int max;
}tr[maxn << 2];

pair<int,int> buildmax(int left,int right,int now)
{
    tr[now].left=left;
    tr[now].right=right;
    if(left==right)
    {
        tr[now].id=left;
        tr[now].max=a[left];
        return make_pair(left,a[left]);
    }
    int mid=(left+right)>>1;

    pair<int,int> r1=buildmax(left,mid,now*2);
    pair<int,int> r2=buildmax(mid+1,right,now*2+1);
    if(r1.second>=r2.second)
    {
        tr[now].id=r1.first;
        tr[now].max=r1.second;
        return r1;
    }
    else
    {
        tr[now].id=r2.first;
        tr[now].max=r2.second;
        return r2;
    }
}

pair<int,int> querymax(int left,int right,int now)
{
    if(left == tr[now].left && right == tr[now].right)
        return make_pair(tr[now].id,tr[now].max);
    int mid=(tr[now].left+tr[now].right)>>1;

    if(right<=mid)
        return querymax(left, right, now << 1);
    else if(left>mid)
        return querymax(left, right, now << 1 | 1);
    else
    {
        pair<int,int> r1=querymax(left, mid, now << 1);
        pair<int,int> r2=querymax(mid+1, right, now << 1 | 1);
        return r1.second >= r2.second ? r1 : r2;
    }
}
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    buildmax(1, n, 1);
    int ql = 1, qr = n - m + 1;
    for(int i = 1; i <= m; ++i){
        pair<int, int>res = querymax(ql, qr, 1);
        printf("%d%c", res.second, i == m ? '\n' : ' ');
        ql = res.first + 1;
        qr++;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章