专栏文章
ARC194B题解
AT_arc194_b题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipxkj7a
- 此快照首次捕获于
- 2025/12/03 19:35 3 个月前
- 此快照最后确认于
- 2025/12/03 19:35 3 个月前
首先贪心地考虑(好吧我是看样例看出来的),按照数值从大到小的顺序来操作。即先将更大的数排到它应该去的位置。
然后我们考虑对于每一个数它产生的代价。对于第 个数,我们假设它最后会排到第 位。会发现,当我们要去操作这个数的时候,它会因为它左边的比它更大的数已经排到右边而向左移。我们设它左边的比它更大的数有 个,则它会产生的代价应该是 。这个式子是等差数列求和算出来的,其中首项应该是 ,末项是 。
然后我们考虑 的求法。这其实就是一个求逆序对的求法,只不过固定了一个数,用线段树或者树状数组即可。
然后我们考虑对于每一个数它产生的代价。对于第 个数,我们假设它最后会排到第 位。会发现,当我们要去操作这个数的时候,它会因为它左边的比它更大的数已经排到右边而向左移。我们设它左边的比它更大的数有 个,则它会产生的代价应该是 。这个式子是等差数列求和算出来的,其中首项应该是 ,末项是 。
然后我们考虑 的求法。这其实就是一个求逆序对的求法,只不过固定了一个数,用线段树或者树状数组即可。
代码
CPP#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
const int MAXN = 2e5+5;
ll n;
ll p[MAXN];
ll qd[MAXN]; //前面的大于 p[i] 的个数
pll ps[MAXN];
//树状数组
ll lowbit(ll x)
{
return (x&(-x));
}
ll c[MAXN];
ll Sum(ll x)
{
ll sum = 0;
for(ll i = x;i > 0;i -= lowbit(i))
{
sum += c[i];
}
return sum;
}
void modify(ll x,ll k)
{
for(ll i = x;i <= n;i += lowbit(i))
{
c[i] += k;
}
return;
}
int main()
{
scanf("%d", &n);
for(int i = 1;i <= n;i++)
{
scanf("%lld", &p[i]);
qd[i] = Sum(n) - Sum(p[i]);
modify(p[i], 1LL);
// 这两行就是计算在 p[i] 前面的大于 p[i] 的数的个数
ps[i] = pll(p[i], i);
}
sort(ps + 1, ps + n + 1);
ll ans = 0;
for(int i = 1;i <= n;i++)
{
//ps[i].second 对应前文的 i
//qd[ps[i].second] 对应前文的 x
//i 对应前文的 j
ll nowid = ps[i].second - qd[ps[i].second];
ans += ((nowid-1 + i) * (ll)abs(nowid - i) >> 1LL);
}
printf("%lld", ans);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...