CodeForces 1269E K Integers solving report Fenwick tree-half reverse order
Problem-solving ideas: Fenwick tree, reverse order, two points. Meaning of the questions is to give a set of numbers, in turn let you ask discharge switching sequence of at least 1 to k times in the array, (k varying from 1 to n, each plus 1), at first I thought of him as a simple reverse to do in ascending order, on the wa. This question is a multi-step, multi-coupled to the numbers 1 to k of these against the price together.
Finally a little taste of the algorithm, so hard.
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 1000010;
const int maxn = 1e9;
using namespace std;
ll a[200005];
ll sum[200005];
ll sum2[200005];
ll pos[200005];
ll n;
ll lowbit(ll x)
{
return x &(-x);
}
void add(ll sum[], ll x, ll v)
{
while (x <= n)
{
sum[x] += v;
x += lowbit(x);
}
}
ll query(ll sum[], ll x)
{
ll res = 0;
while (x > 0)
{
res += sum[x];
x -= lowbit(x);
}
return res;
}
int main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
pos[a[i]] = i;//记录每个数的初始下标,即在数组中的位置
}
ll ansl = 0;
for (int i = 1; i <= n; i++)
{
ansl += i - 1 - query(sum, pos[i]);//这里求逆序对
add(sum, pos[i], 1);//这棵树用来求逆序对
add(sum2, pos[i], pos[i]);//这棵树用来求将数靠在一起需要的代价
ll mid;
ll l = 1, r = n;
while (l <= r)
{
mid = (l + r) >> 1;
if (query(sum, mid) * 2 <= i)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
ll ansr = 0;//这里求将1到k的数靠在一起需要的代价
ll cnt = query(sum, mid), all = query(sum2, mid);
ansr += mid * cnt - all - cnt * (cnt - 1) / 2;
cnt = i - cnt, all = query(sum2, n) - all;
ansr += all - cnt * (mid + 1) - cnt * (cnt - 1) / 2;
printf("%lld ", ansl + ansr);
}
}