P2448 无尽的生命 题解
简要分析
求逆序对,但是元素很多(\(\le 2^{31} - 1\),\(2 \times 10^9\) 多一点),由于题目给出的 \(k\) 却比较小,所以我们可以从 \(k\) 入手:
显而易见,\(2 \times 10^9\) 的元素中最多只会有 \(2 \times 10^5\) 个被交换(不会重复交换一个元素),而剩下的大量数据如果都储存下来,是没有意义的。
我们可以将没有参与交换的元素中,连续的部分看成一个整体,这里就用到了离散化的思想,将这些元素合并以后,剩下的元素就可以 \(O(n \log n)\) 求逆序对了。
逆序对
逆序对怎么求,这里我们可以用树状数组求。由于这个不是模板题,不再解释。(都是紫题了还要讲逆序对?)
但是在这道题中,一部分元素是包含多个元素的,怎么办?
这就可以用到权值逆序对:我们在查找的过程中,现在发现了一个现在数组中的一对逆序对 \(S_i > S_j\)(\(i < j\)),\(S_i\) 包含 \(t_i\) 个元素,\(S_j\) 包含 \(t_j\) 个元素。因为只有连续的区间才会被合并,所以 \(S_i\) 包含的所有元素都大于 \(S_j\) 中的任意元素。
因此,\(S_i\) 和 \(S_j\) 对答案的贡献为 \(t_i \times t_j\)。
细节和易错点
-
数组别开的太小,会 RE 的,我开到了 \(4 \times 10^5\)。
-
\(10^5\) 级别的数据,不开
long long
怎么行?
代码
(由于我大量使用了 STL,所以效率并不太高 懒 呵呵)
#include <bits/stdc++.h>
#define int long long
#define rr read()
using namespace std;
const int N = 4e5 + 10;
// 快读
inline int read()
{
int num = 0, flag = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
flag = -1;
for (; isdigit(ch); ch = getchar())
num = (num << 3) + (num << 1) + ch - '0';
return num * flag;
}
// 存放元素
struct node
{
int x, y;
node()
{
x = y = 0;
}
node(int _x, int _y)
{
x = _x, y = _y;
}
bool operator<(const node &t) const
{
return x < t.x;
}
};
vector<node> q;
vector<node> a;
set<node> uq;
set<node> ad;
unordered_map<int, int> to;
// 树状数组
int s[N];
inline int lobit(int x)
{
return x & -x;
}
void upd(int x, int t)
{
for (; x < N; x += lobit(x))
s[x] += t;
}
int que(int x)
{
int res = 0;
for (; x; x -= lobit(x))
res += s[x];
return res;
}
signed main()
{
int m = rr;
for (int i = 0; i < m; ++i)
q.push_back({rr, rr}), uq.emplace(q[i].x, 1), uq.emplace(q[i].y, 1);
// 去重和合并
set<node>::iterator _a = uq.begin(), _b(_a);
for (++_b; _b != uq.end(); ++_a, ++_b)
if (_a->x < _b->x - 1)
ad.emplace(_b->x - 1, _b->x - _a->x - 1);
uq.insert(ad.begin(), ad.end());
int n = 0;
for (node i : uq)
to[i.x] = n++, a.push_back({n, i.y});
// 进行交换操作
for (int i = 0; i < m; ++i)
swap(a[to[q[i].x]], a[to[q[i].y]]);
// 求逆序对
int ans = 0;
for (int i = n - 1; i >= 0; --i)
{
ans += que(a[i].x - 1) * a[i].y;
upd(a[i].x, a[i].y);
}
printf("%lld\n", ans);
return 0;
}
本文来自博客园,作者:RainPPR,转载请注明原文链接:https://www.cnblogs.com/RainPPR/p/solution-p2448.html
如有侵权请联系我(或 2125773894@qq.com)删除。