P4867 Gty的妹子序列 Solution

Description

给定序列 a = ( a 1 , a 2 , ⋯   , a n ) a=(a_1,a_2,\cdots,a_n) a=(a1,a2,,an),有 m m m 个查询 ( l , r , L , R ) (l,r,L,R) (l,r,L,R).
对于每个查询,你需要求出 ∑ k = L R [ k ∈ a l ⋯ r ] \sum\limits_{k=L}^R[k\in a_{l\cdots r}] k=LR[kalr].

Limitations

1 ≤ n ≤ 1 0 5 1\le n\le 10^5 1n105
1 ≤ m ≤ 1 0 6 1\le m\le 10^6 1m106
1 ≤ a i ≤ n 1\le a_i\le n 1ain
1 ≤ l ≤ r ≤ n 1\le l \le r \le n 1lrn
1 ≤ L ≤ R ≤ n 1\le L\le R\le n 1LRn
5 s , 32 MB 5\text{s},\textcolor{red}{32\text{MB}} 5s,32MB

Solution

空间限制很小,只能用莫队.
考虑 adddel,需要一个 ds 支持值域上单点加,区间和.
值域只有 1 0 5 10^5 105,显然可用 BIT 直接维护.
当然,为了根号平衡,还可用值域分块.
BIT 的时间复杂度为 O ( n m log ⁡ n ) O(n\sqrt m\log n) O(nm logn)
用分块的时间复杂度为 O ( n m + m n ) O(n\sqrt m+m\sqrt n) O(nm +mn ).
可能要调块长.

Code

3.02 KB , 3.01 s , 24.55 MB    (in   total,   C++20   with   O2) 3.02\text{KB},3.01\text{s},24.55\text{MB}\;\texttt{(in total, C++20 with O2)} 3.02KB,3.01s,24.55MB(in total, C++20 with O2)
代码用的分块,但 fastio 删了.


#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;

template<class T>
bool chmax(T &a, const T &b){
	if(a < b){ a = b; return true; }
	return false;
}

template<class T>
bool chmin(T &a, const T &b){
	if(a > b){ a = b; return true; }
	return false;
}

// #define LOCAL
#ifdef LOCAL
#define getchar_unlocked getchar
#define putchar_unlocked putchar
#endif

// fastio

int lowbit(int x){
	return x & -x;
}

// block
struct Block {
	int n, size, blocks;
	vector<int> a, s;
	inline Block() {}
	inline Block(int _n, int _size) : n(_n), size(_size) {
		blocks = (n + size - 1) / size;
		a.resize(n);
		s.resize(blocks);
	}
	
	inline int L(int x) { return size * x; }
	inline int R(int x) { return min(n, L(x) + size) - 1; }
	
	inline void add(int x, int v) { a[x] += v, s[x / size] += v; }
	inline int _ask(int l, int r) {
		int res = 0;
		for (int i = l; i <= r; i++) res += a[i];
		return res;
	}
	
	inline int ask(int l, int r) {
		const int bl = l / size, br = r / size;
		if (bl == br) return _ask(l, r);
		int res = _ask(l, R(bl)) + _ask(L(br), r);
		for (int i = bl + 1; i < br; i++) res += s[i];
		return res;
	}
};
struct Query { 
    int l, r, a, b, id;
    inline Query() {}
    inline Query(int _l, int _r, int _a, int _b, int _id) 
         : l(_l), r(_r), a(_a), b(_b), id(_id) {}
}; 

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	const int n = read<int>(), m = read<int>();
	vector<int> a(n);
	for (int i = 0; i < n; i++) a[i] = read<int>(), a[i]--;
	
	const int B = sqrt(n);
	vector<int> cnt(n);
	Block bit(n, B);
	
	auto add = [&](int x) {
		if (cnt[x]++ == 0) bit.add(x, 1);
	};
	auto del = [&](int x) {
		if (--cnt[x] == 0) bit.add(x, -1);
	};
	
	vector<Query> qry(m);
	for (int i = 0, l, r, a, b; i < m; i++) {
		scanf("%d %d %d %d", &l, &r, &a, &b);
		l--, r--, a--, b--;
		qry[i] = Query(l, r, a, b, i);
	}
	
	
	sort(qry.begin(), qry.end(), [&](const Query &a, const Query &b) {
        if (a.l / B == b.l / B) {
            return a.r < b.r;
        }
        return a.l / B < b.l / B;
    });
	
	vector<int> ans(m);
	int l = 0, r = -1;
	for (auto [ql, qr, qa, qb, id] : qry) {
		while (ql < l) add(a[--l]);
        while (r < qr) add(a[++r]);
        while (l < ql) del(a[l++]);
        while (qr < r) del(a[r--]);
        ans[id] = bit.ask(qa, qb);
	}
	
	for (int i = 0; i < m; i++) {
        write(ans[i]);
        putchar_unlocked('\n');
    }
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值