您的位置:首页 > 其它

BZOJ3744 Gty的妹子序列

2014-11-16 09:42 295 查看
我kao终于搞定了。。。

总之妹子序列比妹子树好些。。。妹子树至今还不会。。。

这题就是强制在线的区间逆序对个数。。。

神马主席树的太高端了。。。早忘了。。。额T T(怪我咯?><)

首先我们分块,求出连续块内的答案,方法是直接用BIT暴力求。。。

复杂度为O(n ^ 2 / size * log(n ^ 2 / size))(size为一块的大小)

然后回答的时候,中间整段的都有了,只要看两边多出来的就可以了,方法是直接用BIT暴力求。。。额。。。

查询一次的最坏复杂度为O(2size * log(size))(size为一块的大小)

总之就是暴力求。。。

接着我们来看一下了啦~~~size去什么值比较好呢?

n ^ 2 / size * log(n ^ 2 / size) + m * size * log(size)最小。。

神马展开的。。。然后求导。。。我去。。。

那些数学高联1=的人。。。你倒是给我算出来啊!

还是乖乖地取size = sqrt(n)算了。。。

/**************************************************************
Problem: 3744
User: rausen
Language: C++
Result: Accepted
Time:10876 ms
Memory:50872 kb
****************************************************************/

#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
, st[B];
int BIT
, vis
;
int ans[B][B];
int cnt[B]
;
int a
, b
;

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
;
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;
}


View Code
(p.s. Rank10貌似还可以的样子。。。话说小号为了调参连T5次。。。估计是快要被权限掉了Orz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: