题解:P12386 [蓝桥杯 2023 省 Python B] 混乱的数组
Heyg_future · · 题解
[蓝桥杯 2023 省 Python B] 混乱的数组
题目传送门
Solution
看到本题,先来一发打表。 毕竟是构造题,必须要找找规律。
4: 2 2 1 1
5: 3 2 1 1
6: 4 3 2 1
7: 2 3 2 1 1
8: 3 2 2 1 1
9: 4 3 2 1 1
10: 5 4 3 2 1
11: 2 4 3 2 1 1
12: 3 3 2 2 1 1
13: 4 3 2 2 1 1
14: 5 4 3 2 1 1
15: 6 5 4 3 2 1
16: 2 5 4 3 2 1 1
17: 3 4 3 2 2 1 1
18: 4 3 3 2 2 1 1
19: 5 4 3 2 2 1 1
20: 6 5 4 3 2 1 1
21: 7 6 5 4 3 2 1
22: 2 6 5 4 3 2 1 1
23: 3 5 4 3 2 2 1 1
24: 4 4 3 3 2 2 1 1
25: 5 4 3 3 2 2 1 1
26: 6 5 4 3 2 2 1 1
27: 7 6 5 4 3 2 1 1
28: 8 7 6 5 4 3 2 1
然后惊人地发现竟然对于所有最优解为
证明一下,当每一位都与其前面的全部位数构成逆序对时,其逆序对数
那么贪心地,则可以找出可以拼出最多的逆序对的
long long n=1;
while(n*n-n<2*x) n++;
那么这个临界值可以特判输出,它们刚好是一个递减等差数列,首项为
if((n*n-n)/2==x){
cout<<n<<"\n";
for(int i=n;i>=1;i--)
cout<<i<<" ";
}
然后再仔细观察可以发现,对于每组答案数列来说,有一部分里的数从第一个开始单调递减,有一部分,从第二个数开始单调递减。
第一种情况。
此部分的
因为,每次将第
第二种情况。
此部分的
和上一种一样,只是将
简单证明一下。因为在临界情况
最终代码如下。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
long long x,a[N];
int main(){
cin>>x;
long long n=1;
while(n*n-n<2*x) n++;
if((n*n-n)/2==x){
cout<<n<<"\n";
for(int i=n;i>=1;i--)
cout<<i<<" ";
}
else {
cout<<n<<"\n";
//n为数列长度
int p=(n+1)/2,d=(n*n-n)/2,tp=0;
for(int i=1;i<=n;i++){
if(i%2) tp++;
a[i]=tp;
}
if(x>=d-p){
int t=d-x;
for(int i=1;i<=n;i++)
if(a[i]>d-x) a[i]=++t;
}
else {
a[n]=n/2-(d-p-x);
int t=a[n-1]+d-p-x;
for(int i=n-1;t>a[i-1]&&t>1;i--)
a[i]=t--;
}
for(int i=n;i>=1;i--)
cout<<a[i]<<" ";
}
return 0;
}
这样即可通过此题。