2012 ACM/ICPC Asia Regional Online Warmup 1006题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
int sum[maxn<<2];
int pos[maxn];
int n;
void build(int l, int r, int rt)
{
if (l == r) {
sum[rt] = 1;
return ;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void update(int l, int r, int rt, int p, int c)
{
if (l == r) {
sum[rt] += c;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(l, m, rt << 1, p, c);
else update(m + 1, r, rt << 1 | 1, p, c);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
int querySum(int l, int r, int rt, int L, int R)
{
if (L <= l && R >= r) {
return sum[rt];
}
int m = (l + r) >> 1;
int ret = 0;
if (L <= m) ret += querySum(l, m, rt << 1, L, R);
if (R > m) ret += querySum(m + 1, r, rt << 1 | 1, L, R);
return ret;
}
int queryPos(int l, int r, int rt, int s)
{
if (l == r) {
return l;
}
int m = (l + r) >> 1;
if (s <= sum[rt<<1]) {
return queryPos(l, m, rt << 1, s);
}
return queryPos(m + 1, r, rt << 1 | 1, s - sum[rt<<1]);
}
int main()
{
while (scanf("%d", &n) != EOF) {
if (n == 0) break;
int k;
for (int i = 1; i <= n; ++i) {
scanf("%d", &k);
pos[k] = i;
}
build(1, n, 1);
__int64 ans = 0;
int curpos = 1;
for (int i = 1; i <= n; ++i) {
int tmp;
if (curpos == pos[i]) {
ans += 1;
} else if (curpos < pos[i]) {
int tmp = querySum(1, n, 1, curpos + 1, pos[i]);
ans += min(tmp, n - i + 1 - tmp) + 1;
} else {
int tmp = querySum(1, n, 1, pos[i], curpos - 1);
ans += min(tmp, n - i + 1 - tmp) + 1;
}
update(1, n, 1, pos[i], -1);
int s = querySum(1, n, 1, 1, pos[i]);
if (s < n - i) {
curpos = queryPos(1, n, 1, s + 1);
} else {
curpos = queryPos(1, n, 1, 1);
}
}
printf("%I64d\n", ans);
}
return 0;
}