51nod 1153 選擇子串行 (好題)

2021-08-04 14:19:24 字數 1560 閱讀 3908

這個題很不錯。

採用貪心的思想:首先考慮到在整個序列中取最大值一定是最優的,也就是說b陣列的第乙個數是a陣列的中最大值的下標。而且通過題意我們發現,一旦選定了某個數就把當前的區間劃分成兩份。比如說第一次選了9,第二次選了10, 那麼下一次肯定不會選8(這幾個數字說的都是下標),不會垮區間選數,那麼我們就可以每次選乙個區間最大值,再把區間劃分成兩份分別查詢最大值就可以了。因為每個元素最多訪問一遍,再加上線段樹找最大值,就是nlong的複雜度了

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e5;

int n;

struct pa[maxn * 2];

void build(int root, int l, int r)

int mid = (l + r) >> 1;

build(root << 1, l, mid);

build(root << 1|1, mid + 1, r);

if(a[root << 1].val > a[root << 1|1].val)else

}struct p qu(int root, int l, int r, int s, int t)

int mid = (l + r) >> 1;

if(s <= mid) x = qu(root << 1, l, mid, s, t);

if(t > mid) y = qu(root << 1|1, mid + 1, r, s, t);

if(x.val > y.val) return x;

return y;

}int dfs(int l, int r)

int main()

2017/7/31 更新:

因為這個題目在大佬收錄的「o(n)可以過的好題」裡面,我就重寫了一下,用單調棧代替了線段樹。效率提高了一些吧

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e5;

int a[maxn];

int left[maxn], right[maxn];

int n;

stack

s;int dfs(int t)

int main()

s.push(i);

}for(int i = n; i >= 1; i--)

s.push(i);

}printf("%d\n", dfs(pos));

return

0;}

51nod 1153 選擇子串行

長度為n的整數陣列a,所有的數均不相同,假設下標從0開始。找到乙個最長的陣列b,b陣列的長度為k,數值範圍是0 n 1,記錄的是a陣列的下標。滿足a b 0 a b 1 a b 2 a b k 並且對任意連續的兩項b i 及b i 1 滿足min b i b i 1 j max b i b i 1 ...

選擇子串行 51Nod 1153

長度為n的整數陣列a,所有的數均不相同,假設下標從0開始。找到乙個最長的陣列b,b陣列的長度為k,數值範圍是0 n 1,記錄的是a陣列的下標。滿足ab 0 ab 1 ab 2 ab k 並且對任意連續的兩項b i 及bi 1 滿足min b i bi 1 j max b i bi 1 均有aj ab...

51nod 1153 選擇子串行

51nod 選擇子串行 這道題是 bunny 學長在給我們的模擬賽中的一道題。食用單調棧,處理每個數 a i 左右第乙個比自己大的數的下標 left i right i 並且建兩條有向邊 i,left i i,right i 處理完畢後得到乙個 dag 然後求此圖的拓撲序。由於都是小數連大數,所以可...