題目鏈結
題意:給出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
#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...