当前位置:首页 > GESP > 2023年GESP六级小杨握手问题(洛谷B3874):Fenwick树求解逆序对的代码解析

2023年GESP六级小杨握手问题(洛谷B3874):Fenwick树求解逆序对的代码解析

1天前

2023年GESP六级小杨握手问题(洛谷B3874):Fenwick树求解逆序对的代码解析 GESP考试 算法竞赛 洛谷B3874 Fenwick树 逆序对问题 第1张

一、题目解读

    “小杨的握手问题”源自2023年GESP六级考试(对应洛谷题目B3874)。题目描述为:给定一个长度为N的排列,每次将当前数与之前未访问过的数握手,求总共握手次数。本质上是求排列中逆序对的个数,即统计每个数右侧比它小的元素数量。需设计高效算法在O(NlogN)时间内解决。

二、解题思路

    核心思想是将握手次数转化为逆序对计数问题,利用Fenwick树(二叉索引树)实现动态区间查询与更新。通过维护数组元素的顺序统计信息,每次查询当前数之前已出现数的个数,即为该数的握手次数。关键在于将离散的握手操作转化为可差分维护的区间操作,避免暴力枚举

三、解题步骤

1. 数据预处理:将输入数据转换为1-based索引(原代码中通过order[i]++实现),便于Fenwick树操作。

2. 构建Fenwick树:初始化大小为N的树,初始值全为0。

3. 逆序对统计:

    1.遍历排列顺序,对于每个数current:

    2.查询ft.query(current-1):获取当前位置前比current小的元素个数(即左侧逆序对)。

    3.更新ft.update(current,1):将current加入树中,标记已访问。

4. 累计握手次数:将每次查询结果累加至handshakes变量。

5. 输出结果:最终handshakes即为总握手次数。

四、代码与注释

#include <iostream>
#include <vector>
using namespace std;

class FenwickTree {
private:
   vector<int> tree;
   int size;
public:
   FenwickTree(int n) : size(n), tree(n + 1, 0) {} // 构造函数初始化树大小及全0数组
   
   void update(int index, int delta) {
       for(; index <= size; index += index & -index) // 从index到末尾更新,利用二进制位操作
           tree[index] += delta;
   }
   
   int query(int index) {
       int res = 0;
       for(; index > 0; index -= index & -index) // 从index到1查询,逐步累加
           res += tree[index];
       return res;
   }
};

int main() {
   ios::sync_with_stdio(false);
   cin.tie(nullptr); // 加快输入输出速度
   
   int N;
   cin >> N;
   vector<int> order(N);
   for(int i = 0; i < N; i++) {
       cin >> order[i];
       order[i]++; // 转换为1-based索引,适配Fenwick树操作
   }
   
   FenwickTree ft(N);
   long long handshakes = 0;
   
   for(int i = 0; i < N; i++) {
       int current = order[i];
       handshakes += ft.query(current - 1); // 查询比current小的已存在数个数
       ft.update(current, 1); // 标记当前数已出现
   }
   
   cout << handshakes << endl;
   return 0;
}

五、总结

    本解法通过将握手问题转化为逆序对计数,利用Fenwick树的O(logN)区间查询与更新,实现高效求解。相较于暴力或归并排序等算法,Fenwick树具有代码简洁、常数优化的优势,尤其在处理动态统计问题时表现优异。掌握此类数据结构的应用,对算法竞赛与实际问题求解具有重要意义。




原创内容 转载请注明出处

分享给朋友:

相关文章

洛谷2804题解:基于Fenwick树与离散化的区间统计优化方案

洛谷2804题解:基于Fenwick树与离散化的区间统计优化方案

一、题目解读洛谷2804题要求解决一个涉及区间统计的问题,核心在于高效计算满足特定条件的元素数量。题目可能涉及前缀和、区间查询或计数类操作,需处理大范围数据及可能的负数输入。通过代码分析可知,关键需求...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。