這個題很不錯。
採用貪心的思想:首先考慮到在整個序列中取最大值一定是最優的,也就是說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 然後求此圖的拓撲序。由於都是小數連大數,所以可...