BZOJ 3744 Gty的妹子序列 分块+树状数组

6 篇文章 0 订阅

具体分析见 搬来大佬博客
时间复杂度 O ( n n l o g n ) O(n\sqrt nlogn) O(nn logn)

CODE

#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;

char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
    char ch; int flg = 1; for(;!isdigit(ch=getc());)if(ch=='-')flg=-flg;
    for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 50005;
const int SQRT = 230;
int n, q, a[MAXN], B, bel[MAXN], tail[SQRT], blocks, b[MAXN], tot;
int T[MAXN], f[SQRT][MAXN], g[SQRT][MAXN];

inline void upd(int x, int val) {
	while(x) T[x] += val, x -= x&-x;
}

inline int qsum(int x) {
	int res = 0;
	while(x <= tot) res += T[x], x += x&-x;
	return res;
}

inline void solvef(int i, int s) {
	for(int j = s; j <= n; ++j)
		f[i][j] = f[i][j-1] + qsum(a[j]+1), upd(a[j], 1);
	for(int j = s; j <= n; ++j) upd(a[j], -1);
}

inline void solveg(int i, int t) {
	for(int j = t; j; --j)
		g[i][j] = g[i][j+1] + qsum(1)-qsum(a[j]), upd(a[j], 1);
	for(int j = t; j; --j) upd(a[j], -1);
}

inline int head(int i) { return (i-1)*B + 1; }

int main () {
	read(n); B = sqrt(n);
	blocks = (n-1)/B + 1;
	for(int i = 1; i <= n; ++i)
		read(a[i]), bel[i] = (i-1)/B + 1, tail[bel[i]] = i, b[++tot] = a[i];
	sort(b + 1, b + tot + 1);
	tot = unique(b + 1, b + tot + 1) - b - 1;
	for(int i = 1; i <= n; ++i)
		a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
	for(int i = 1; i <= SQRT; ++i)
		solvef(i, head(i)), solveg(i, tail[i]);
	read(q);
	int lastans = 0, l, r;
	while(q--) {
		read(l), read(r);
		l ^= lastans, r ^= lastans;
		lastans = f[bel[l]][r] + g[bel[r]][l] - f[bel[l]][tail[bel[r]]];
		for(int i = head(bel[l]); i < l; ++i) upd(a[i], 1);
		for(int i = r+1; i <= tail[bel[r]]; ++i) lastans += qsum(a[i]+1);
		for(int i = head(bel[l]); i < l; ++i) upd(a[i], -1);
		printf("%d\n", lastans);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值