51NOD 1364 最大字典序排列 貪心 線段樹

2021-08-18 23:07:05 字數 2675 閱讀 5013

題目鏈結

題意:給出n

nn個數的排列,你有k

kk次操作的機會,每次操作可以將相鄰的兩個數交換位置。

問k

kk次操作以後,能夠得到的字典序最大的排列是什麼?

思路:根據資料範圍,排除了動態規劃的方向。

通過觀察樣例和手算幾組簡單的例子,我們可以發現,排列的第一位應盡可能的大,滿足以後再讓排列第二位盡可能的大…以此類推可以得到最終滿足條件的最優解。

故考慮貪心。

假設前i−1

i-1i−

1位排列已經達到最優的狀態,則對於第i

ii位和當前的k

kk值,首先可以交換的數的範圍是:

[ i+

1,i+

k]

[i+1,i+k]

[i+1,i

+k]隨後從該區間中找出值最大的數mxmx

mx。考慮兩種情況,如果m

x

i]

mx < a[i]

mxi]

的話,則說明第i

ii位的數不用通過交換已經達到了最優的狀態。

否則的話,刪除原來位置的mx,將mxmx

mx插入到 a[i

]a[i]

a[i]

之前,同時更新kkk。

但因為涉及數的插入和刪除,對於順序儲存映像,該問題的總複雜度為不可承受的:o(n

2)

o(n^2)

o(n2

)故考慮用資料結構進行優化。

當我們考慮第i

ii位的情況的時候,前i−1

i-1i−

1位的數是完全不用考慮的,故上述的插入操作是沒有必要的,同時對於刪除操作,我們可以考慮做乙個標記,存在為1

11,刪除為0

00,則對於乙個區間所有存在的數的數量,則可以看成是標記的區間和。

同時又涉及區間最大值,故自然會想到利用線段樹對貪心演算法進行優化。

對於線段樹的每乙個節點,我們維護三個值,區間最大值,區間標記的總和和區間最大值所在的位置。

隨後優化上述的貪心操作即可。

此題得解。

**:

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

#define lson rt<<1

#define rson rt<<1|1

const

int a =

2e5+10;

class

seg_tree

tree[a<<2]

;int a[a]

,ans[a]

,tot,n,k;

void

push_up

(int rt)

void

build_tree

(int rt,

int l,

int r)

int mid =

(l+r)

>>1;

build_tree

(lson,l,mid)

;build_tree

(rson,mid+

1,r)

;push_up

(rt);}

void

query

(int rt,

int sum,

int& p,

int& v)

if(sum <= tree[lson]

.sum)

query

(lson,sum,p,v)

;else

query

(rson,sum-tree[lson]

.sum,p,v);}

void

get_mx

(int rt,

int st,

int ed,

int& p,

int&v)

int mid =

(l+r)

>>

1,now_p =

0,now_v =0;

if(st<=mid)}if

(ed> mid)}}

intget_sum

(int rt,

int st,

int ed)

void

update

(int rt,

int pos)

int mid =

(l+r)

>>1;

if(pos <= mid)

update

(lson,pos)

;else

update

(rson,pos)

;push_up

(rt);}

intmain()

build_tree(1

,1,n);

int p1,v1,p2,v2,p3,mx;

for(

int i=

1;i<=n ;i++

)else

}for

(int i=

1;i<=n ;i++

)return0;

}

51nod1364 最大字典序排列

給出乙個1至n的排列,允許你做不超過k次操作,每次操作可以將相鄰的兩個數交換,問能夠得到的字典序最大的排列是什麼?例如 n 5,k 6,在6次交換後,能夠得到的字典序最大的排列為。input 第1行 2個數n,k中間用空格分隔 1 n 100000,0 k 10 9 第2至n 1行 每行乙個數i 1...

51nod 1364 最大字典序排列

給出乙個1至n的排列,允許你做不超過k次操作,每次操作可以將相鄰的兩個數交換,問能夠得到的字典序最大的排列是什麼?例如 n 5,k 6,在6次交換後,能夠得到的字典序最大的排列為。input 第1行 2個數n,k中間用空格分隔 1 n 100000,0 k 10 9 第2至n 1行 每行乙個數i 1...

51nod 1364 最大字典序排列

online judge 51nod 1364 label 線段樹,樹狀陣列,二分 根據題意很容易想到60 資料的 o n 2logn 暴力做法,即每次從大數往小數找,如果它能在m步內換到當前位置就把它換到前面去,然後再把選中的位置設為0,可以用樹狀陣列在 o logn 完成。cin n for i...