蓝桥杯练习 混乱的数组

原题链接
参考@ExRoc dalao博客
参考@Sliarae dalao博客

硬想很难发现规律 需要打表

@ExRoc dalao的打表代码dfs从小到大暴力枚举每一个数组并判断

长度 :长度 n n n完全逆序列的逆序对数= n ( n − 1 ) 2 {n(n-1)\over 2} 2n(n−1),需要 n ( n − 1 ) 2 ≥ x ≥ ( n − 1 ) ( n − 2 ) 2 {n(n-1)\over 2}\geq x\geq {(n-1)(n-2)\over 2} 2n(n−1)≥x≥2(n−1)(n−2)

构造 :把x分成两部分 x = d + ( l − 1 ) ( l − 2 ) 2 x=d+{(l-1)(l-2)\over 2} x=d+2(l−1)(l−2),先构造出 l − 1 l-1 l−1长度完全逆序列,其中包含一组 1 ∼ d 1\sim d 1∼d的数,最后再在数组最前面加上一个 d + 1 d+1 d+1,补上 d d d个逆序对
l − 1 l-1 l−1长度部分构造方法:

我是按照@Sliarae dalao的思路去理解的 先从一个排列的角度想

首先考虑如果要求 A A A 为排列怎么做:

  1. 找到一个最小的 n n n,使得序列 [ n , n − 1 , ... , 1 ] [n, n-1, \dots, 1] [n,n−1,...,1] 的逆序对数 n ( n − 1 ) 2 ≥ x \frac{n(n-1)}{2} \geq x 2n(n−1)≥x;

  2. 计算 v = n − ( n ( n − 1 ) 2 − x ) v = n - \left( \frac{n(n-1)}{2} - x \right) v=n−(2n(n−1)−x),将数字 v v v 交换到位置 A 1 A_1 A1。(提到最前面)

这样可以使得 A A A 的字典序最小。

然后抛弃排列性质,尽量把前面的值变小,其前提是后面的值尽量小

如 x = 7 = 1 + 4 ⋅ 3 2 x=7=1+\frac{4\cdot 3}{2} x=7=1+24⋅3,构造 2 , 4 , 3 , 2 , 1 2,4,3,2,1 2,4,3,2,1满足 x x x,接着把后面的数尽量变小,让字典序尽量小
2 ^ , 4 , 3 , 1 ‾ , 1 \hat 2,4,3,\underline1,1 2^,4,3,1,1: 2 → 1 2\rightarrow 1 2→1,失去和后面的1的逆序对,但是又和前面2形成,总的个数不变
2 , 4 , 2 ‾ , 1 , 1 2,4,\underline2,1,1 2,4,2,1,1: 3 → 2 3\rightarrow 2 3→2,和前后逆序对都没变
2 , 3 ‾ , 2 , 1 , 1 2,\underline3,2,1,1 2,3,2,1,1: 4 → 3 4\rightarrow 3 4→3,和前后逆序对都没变

所以 l − 1 l-1 l−1长度部分构造方式就是先构造一组 1 ∼ d 1\sim d 1∼d的数,其他的再从1开始递增把剩下的 l − 1 − d l-1-d l−1−d填满,从大到小排序

cpp 复制代码
void solve(){
  int x;cin>>x;
  vector<int>a;
  if(x==0){
    a={1};
  }else if(x==1){
    a={2,1};
  }else if(x==2){
    a={2,1,1};
  }else{
    int l=2;//数组长度
    forr(i,2,x){
      if(i*(i-1)/2>=x){//长度为l的数组 最多有l*(l-1)/2个逆序对
        l=i;
        break;
      }
    }
    //先构造l-1长度完全逆序数组 产生(l-1)*(l-2)/2 (小于x)个逆序对
    int d=x-(l-1)*(l-2)/2;//另外需要构造的逆序对数(最后一个数能产生的逆序对数)
    cout<<d<<' '<<l-d-1<<endl;
    
    //先构造l-1长的逆序数组
    forr(i,1,d){//d+1和1~d的逆序 能贡献d个逆序对
      a.push_back(i);
    }
    forr(i,1,l-d-1){
      a.push_back(i);
    }
    sort(a.begin(),a.end(),greater<int>());
    //再把d+1放进去
    a.insert(a.begin(),d+1);
  }
  cout<<a.size()<<endl;
  for(auto x:a)cout<<x<<' ';cout<<endl;
}
相关推荐
借雨醉东风1 天前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
云泽8081 天前
笔试算法 - 双指针篇(二):四大经典求和题型 + 有效三角形计数问题
c++·算法
十五年专注C++开发1 天前
WaitingSpinnerWidget: 一个高度可配置的自定义Qt等待加载动画组件
开发语言·c++·qt·waitingspinner
qeen871 天前
【数据结构】树的基本概念及存储
c语言·数据结构·c++·学习·
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【区间贪心】:种树
c++·算法·贪心·csp·信奥赛·区间贪心·种树
hi_ro_a1 天前
C++ 哈希表封装 unordered_map /unordered_set
数据结构·c++·算法·哈希算法
c++之路1 天前
C++ 动态内存
java·jvm·c++
橘颂TA1 天前
【Linux】读写锁
大数据·linux·开发语言·c++·读写锁
霍田煜熙1 天前
HuoTian的两赛vlog(游记)~(2026.04.26写)
c++·奥数·双赛·vlog
CoderCodingNo1 天前
【CSP】CSP-J 2019 江西真题 | 次大值 luogu-P5682 (适合GESP四、五级及以上考生练习)
开发语言·c++·算法