Description
我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现她们排成了一个序列,每个妹子有一个美丽度。
Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:”你知道区间
[l,r]中妹子们美丽度的逆序对数吗?”
蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:”强制在线。”
请你帮助一下Autumn吧。
给定一个正整数序列a,对于每次询问,输出al…ar中的逆序对数,强制在线。
Input
第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1…an(ai>0,保证ai在int内)。
接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al…ar中的逆序
对数(若ai>aj且i
Output
对每个询问,单独输出一行,表示al…ar中的逆序对数。
Sample Input
4
1 4 2 3
1
2 4
Sample Output
2
分析
分块调一天//
简直愉快
代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#define lowbit(x) x & -x
using namespace std;
const int N = 50005;
const int B = 250;
int n, m;
int T, block, size;
int pos[N], st[B];
int BIT[N], vis[N];
int ans[B][B];
int cnt[B][N];
int a[N], b[N];
inline int read()
{
int x = 0;
char ch = getchar();
while (!isdigit(ch))
ch = getchar();
while (isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
inline int find(const int x)
{
int l = 1, r = n + 1, mid;
while (l + 1 < r)
{
mid = (l + r) >> 1;
if (b[mid] <= x) l = mid;
else r = mid;
}
return l;
}
inline void add(int x)
{
while (x <= n)
{
if (vis[x] != T) vis[x] = T, BIT[x] = 1;
else ++BIT[x];
x += lowbit(x);
}
}
inline int query(int x)
{
int res = 0;
while(x)
{
if (vis[x] == T)
res += BIT[x];
x -= lowbit(x);
}
return res;
}
int Work(int l, int r)
{
++T;
if (pos[l] == pos[r])
{
int res = 0;
for (; r >= l; --r)
res += query(a[r] - 1), add(a[r]);
return res;
}
int res, cnt_all, i;
res = ans[pos[l] + 1][pos[r] - 1];
cnt_all = st[pos[r]] - st[pos[l] + 1];
for (i = st[pos[l] + 1] - 1; i >= l; --i)
{
res += query(a[i] - 1) + cnt[pos[r] - 1][a[i] - 1] - cnt[pos[l]][a[i] - 1];
add(a[i]), ++cnt_all;
}
for (i = st[pos[r]]; i <= r; ++i)
{
res += cnt_all - query(a[i]) - cnt[pos[r] - 1][a[i]] + cnt[pos[l]][a[i]];
add(a[i]), ++cnt_all;
}
return res;
}
void Block()
{
int i;
size = (int) sqrt(n);
for (i = 1; i <= n; ++i)
pos[i] = (i - 1) / size + 1;
block = pos[n];
for (i = 1; i <= block; ++i)
st[i] = size * (i - 1) + 1;
st[block + 1] = n + 1;
}
void pre_work()
{
int cnt_now, cnt_all, i, j, k;
for (i = 1; i <= block; ++i)
{
cnt_now = cnt_all = 0, ++T;
memcpy(cnt[i], cnt[i - 1], sizeof(cnt[i]));
for (j = i; j <= block; ++j)
for (k = st[j]; k <= st[j + 1] - 1; ++k)
{
cnt_now += cnt_all - query(a[k]);
ans[i][j] = cnt_now;
add(a[k]);
++cnt_all, ++cnt[j][a[k]];
}
}
for (i = 1; i <= block; ++i)
for (j = 2; j <= n; ++j)
cnt[i][j] += cnt[i][j - 1];
}
int main()
{
int i;
n = read();
for (i = 1; i <= n; ++i)
a[i] = b[i] = read();
m = read();
sort(b + 1, b + n + 1);
for (i = 1; i <= n; ++i)
a[i] = find(a[i]);
Block();
pre_work();
int L, R, ans = 0;
while (m--)
{
L = read() ^ ans, R = read() ^ ans;
printf("%d\n", ans = Work(L, R));
}
return 0;
}