摘要:2022”杭电杯“中国大学生算法设计超级联赛第六场1012
原题链接:
题目描述:
You are given an array aa of length nn. You must perform exactly kk times operations.
For each operation,
First, you select two integers l,rl,r ((1\leq l\leq r \leq n1≤l≤r≤n)),
Second, change aa to bb, satisfy :
∘ For each ii ((1\le i< l1≤i<l)) , b_i=a_ibi=ai;
∘ For each ii ((l\le i< rl≤i<r)) , b_i=a_{i+1}bi=ai+1;
∘ b_r=a_lbr=al
∘ For each ii ((r< i\le nr<i≤n)) , b_i=a_ibi=ai;
Find the lexicographically largest possible array after kk times operations.
Array xx is lexicographically greater than array yy if there exists an index ii (( 1\leq i\leq n1≤i≤n )) such that x_ixi >> y_iyi and for every j (1\leq j \lt i) ,j(1≤j<i), x_j=y_jxj=yj.
题目大意:
给一个n个数的数组,可以进行k次操作,每次操作都可以任选一个下标区间[l,r],将这个下标区间内的元素循环左移。要求求出严格进行k次操作后,能得到的最大字典序的数组。
解题思路:
循环左移,那么最左边的那位一定会被移动[l,r]的最右边。
利用这个特性,我们可以每次操作都移动一个最小的到右边。同样最小则移动靠左的那个,
如果k大于等于n,那么我们可以直接把整个数组变成降序,
如果k小于n,我们可以操作k次把个最小的数字移动到最右边降序排序,
除了这k个数字,,,其他数字的相对顺序是保持不变的。
比如:当初始序列为1 4 2 1 4 2 4,k = 3时,操作过程如下:
第一次操作:因为当前还未处理过的数字当中最小的是1,有多个1,我们选择处理最左边的这个,所以我们选择操作区间[1,7],对区间[1,7]进行循环左移之后之后1到了区间的最右边,也就是第7位。此时序列为4 2 1 4 2 4 1;
第二次操作:因为此时还未处理过的数字当中最小的是1,所以我们选择操作区间[3,6],对区间[3.6]进行循环左移之后1到了区间的最右边,也就是第6位。此时序列为4 2 4 2 4 1 1;
第三次操作:因为此时还未处理过的数字当中最小的是2,所以我们选择操作区间[2,5],对区间[2,5]进行循环左移之后2到了区间的最右边,也就是第5位。最终得到的序列为4 4 2 4 2 1 1。
代码(CPP):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e3 + 10;
/*
循环左移,那么最左边的那位一定会被移动[l,r]的最右边。
利用这个特性,我们可以每次都移动一个最小的到右边。同样最小则移动靠左的那个,
如果k大于等于n,那么我们可以直接把整个数组变成降序,
如果k小于n,我们可以操作k次把个最小的数字移动到最右边降序排序,
除了这k个数字,,,其他数字的相对顺序是保持不变的。
*/
int main()
{
freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
{
vector<int> a;
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
a.push_back(x);
}
if(k >= n)
{
sort(a.begin(), a.end(), greater<int>());
for (int i = 0; i < n; i++)
{
if(i != 0)
cout << " ";
cout << a[i];
}
cout << "\n";
}
else
{
vector<int> b = a;
sort(b.begin(), b.end());
map<int, int> mp;
for (int i = 0; i < k; i++)
{
mp[b[i]]++;
}
bool fst = true;
for (int i = 0; i < n; i++)
{
if(mp[a[i]] > 0)
{
--mp[a[i]];
continue;
}
if(!fst)
cout << " ";
fst = false;
cout << a[i];
}
for (int i = k - 1; i >= 0; i--)
{
cout << " " << b[i];
}
cout << "\n";
}
}
return 0;
}