题解:AcWing 241 楼兰图腾
【题目来源】
AcWing:241. 楼兰图腾 - AcWing题库
【题目描述】
在完成了分配任务之后,西部 \(314\) 来到了楼兰古城的西部。
相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(V),一个部落崇拜铁锹(∧),他们分别用 V 和 ∧ 的形状来代表各自部落的图腾。
西部 \(314\) 在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了 \(n\) 个点,经测量发现这 \(n\) 个点的水平位置和竖直位置是两两不同的。
西部 \(314\) 认为这幅壁画所包含的信息与这 \(n\) 个点的相对位置有关,因此不妨设坐标分别为 \((1,y_1),(2,y_2),\dots,(n,y_n)\),其中 \(y_1\sim y_n\) 是 \(1\) 到 \(n\) 的一个排列。
西部 \(314\) 打算研究这幅壁画中包含着多少个图腾。
如果三个点 \((i,y_i),(j,y_j),(k,y_k)\) 满足 \(1\le i\lt j\lt k\le n\) 且 \(y_i>y_j,y_j<y_k\),则称这三个点构成 V 图腾;
如果三个点 \((i,y_i),(j,y_j),(k,y_k)\) 满足 \(1\le i\lt j\lt k\le n\) 且 \(y_i<y_j,y_j>y_k\),则称这三个点构成 ∧ 图腾;
西部 \(314\) 想知道,这 \(n\) 个点中两个部落图腾的数目。
因此,你需要编写一个程序来求出 V 的个数和 ∧ 的个数。
【输入】
第一行一个数 \(n\)。
第二行是 \(n\) 个数,分别代表 \(y_1,y_2,\dots,y_n\)。
【输出】
两个数,中间用空格隔开,依次为 V 的个数和 ∧ 的个数。
【输入样例】
5
1 5 3 2 4
【输出样例】
3 4
【解题思路】

【算法标签】
《AcWing 241 楼兰图腾》 #树状数组# #线段树# #分块#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long // 使用long long类型
const int N = 200005; // 定义数组最大长度
int n; // 数组长度
int a[N]; // 存储原始数组
int tr[N]; // 树状数组
int Greater[N]; // 存储每个元素右边比它大的元素个数
int Lower[N]; // 存储每个元素右边比它小的元素个数
// 计算x的最低有效位(用于树状数组索引计算)
int lowbit(int x)
{
return x & -x;
}
// 向树状数组添加值:在位置x增加c
void add(int x, int c)
{
// 从x开始向上更新所有相关节点
for (int i = x; i <= n; i += lowbit(i))
{
tr[i] += c;
}
}
// 查询前缀和:计算前x个元素的和
int query(int x)
{
int res = 0;
// 从x开始向下累加所有相关节点
for (int i = x; i; i -= lowbit(i))
{
res += tr[i];
}
return res;
}
signed main()
{
// 输入数组长度n
cin >> n;
// 输入原始数组
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
// 第一遍扫描:从左到右计算每个元素左边的情况
for (int i = 1; i <= n; i++)
{
int y = a[i];
// 计算当前元素右边比它大的元素个数
Greater[i] = query(n) - query(y);
// 计算当前元素右边比它小的元素个数
Lower[i] = query(y - 1);
// 将当前元素加入树状数组
add(y, 1);
}
// 重置树状数组
memset(tr, 0, sizeof(tr));
int res1 = 0, res2 = 0; // res1-逆序对总数,res2-顺序对总数
// 第二遍扫描:从右到左计算结果
for (int i = n; i; i--)
{
int y = a[i];
// 计算逆序对总数
res1 += Greater[i] * (query(n) - query(y));
// 计算顺序对总数
res2 += Lower[i] * (query(y - 1));
// 将当前元素加入树状数组
add(y, 1);
}
// 输出结果:逆序对总数和顺序对总数
cout << res1 << " " << res2 << endl;
return 0;
}
【运行结果】
5
1 5 3 2 4
3 4
浙公网安备 33010602011771号