dls的数据结构-分块,莫队

例题1

#include<bits/stdc++.h>

using namespace std;
const int N = 2e5+10;
typedef long long LL;

const int M = 500;
LL tag[M + 5][M + 5];
LL val[N];
int main(){
	int n, q; scanf("%d %d", &n, &q);
	for(int i = 0; i < q; i ++){
		int op; scanf("%d", &op);
		if(op == 1){
			int x, y, d; scanf("%d %d %d", &x, &y, &d);
			if(x <= M){
				tag[x][y] += d;
			}
			else{
				for(int j = y; j <= n; j += x) val[j] += d;
			}
		}
		else{
			int x; scanf("%d", &x);
			LL ans = val[x];
			for(int j = 1; j <= M; j ++){
				ans += tag[j][x % j];
			}
			printf("%lld\n", ans);
		}
	}
	return 0;
}

#include<bits/stdc++.h>

using namespace std;
const int N = 1e6+10;
const int LOGN = 21;


int n, q;
long long val[N], f[22][N];
void init(){
    // 这里注意val可能存在的边界问题
    for(int i = 1; i <= n; i ++) f[0][i] = val[i];
    for(int i = 1; i < LOGN; i ++){
        for(int j = 1; j + (1 << (i - 1)) <= n; j ++){
            f[i][j] = max(f[i - 1][j + (1 << (i - 1))], f[i - 1][j]);
        }
    }
}

unsigned int A, B, C;
inline unsigned int rng61() {
    A ^= A << 16;
    A ^= A >> 5;
    A ^= A << 1;
    unsigned int t = A;
    A = B;
    B = C;
    C ^= t ^ A;
    return C;
}

int main(){
	scanf("%d%d%u%u%u", &n, &q, &A, &B, &C);
	for(int i = 1; i <= n; i ++) val[i] = rng61();
	init();
	long long res = 0;
	while(q --){
		int l =  rng61() % n + 1, r = rng61() % n + 1;
		if(l > r) swap(l, r);
		int len = __lg(r - l + 1);
		res ^= max(f[len][l], f[len][r - (1 << len) + 1]);
	}
	cout << res << endl;
}

补充

a1 + a2 + a3 + a4 .... + ak = n, 最多有根号n个不同的数

莫队

加一个数,删一个数容易做容易实现
区间查询变成n*根号n次的加数和删数的操作
根据询问的区间,按照左端点所在的块进行分类

#include<bits/stdc++.h>

using namespace std;
const int N = 5e4+10;
typedef long long LL;
array<int, 3> que[N];
int cnt[N], c[N];
LL ans[N], res[N];

LL gcd(LL a, LL b){
	return b ? gcd(b, a % b) : a;
}
int main(){
	int n, m; scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%d", &c[i]);
	for(int i = 1; i <= m; i ++){
		int l, r; scanf("%d %d", &l, &r);
		que[i] = {l, r, i};
		res[i] = (LL)(r - l + 1) * (r - l) / 2;
	}
	const int M = 500;
	sort(que + 1, que + n + 1, [&](array<int, 3> a, array<int, 3> b){
		int id = a[0] / M;
		if(id != b[0] / M) return id < b[0] / M;
		else return id % 2 ? a[1] < b[1] : a[1] > b[1]; 
	});
	
	int tmp = 0;
	auto add = [&](int x){
		tmp += cnt[c[x]];
		cnt[c[x]] ++;
	};
	auto del = [&](int x){
		cnt[c[x]] --;
		tmp -= cnt[c[x]];
	};

	int l = 1, r = 0;
	for(int i = 1; i <= m; i ++){
		while(r > que[i][1]) del(r), r --;
		while(l < que[i][0]) del(l), l ++;	    
		while(r < que[i][1]) r ++, add(r);
		while(l > que[i][0]) l --, add(l);

		ans[que[i][2]] = tmp;
	}
	for(int i = 1; i <= m; i ++){
		LL d = gcd(ans[i], res[i]);
		printf("%lld/%lld\n", ans[i] / d, res[i] / d);
	}
}

include<bits/stdc++.h>

using namespace std;
const int N = 1e5+10;
typedef long long LL;
array<int, 4> que[N];
int cnt[N], c[N], num[N];
int ans[N];

int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &c[i]);
int m; scanf("%d", &m);
for(int i = 1; i <= m; i ++){
int l, r, k; scanf("%d %d %d", &l, &r, &k);
que[i] = {l, r, k, i};
}

const int M = 500;
sort(que + 1, que + m + 1, [&](array<int, 4> a, array<int, 4> b){
	int id = a[0] / M;
	if(id != b[0] / M) return id < b[0] / M;
	else return id % 2 ? a[1] < b[1] : a[1] > b[1]; 
});


auto add = [&](int x){
	num[cnt[c[x]]] --;
	cnt[c[x]] ++;
	num[cnt[c[x]]] ++;
};
auto del = [&](int x){
	num[cnt[c[x]]] --;
	cnt[c[x]] --;
	num[cnt[c[x]]] ++;
};

int l = 1, r = 0;
for(int i = 1; i <= m; i ++){
	while(r > que[i][1]) del(r), r --;
	while(l < que[i][0]) del(l), l ++;	    
	while(r < que[i][1]) r ++, add(r);
	while(l > que[i][0]) l --, add(l);
	ans[que[i][3]] = num[que[i][2]];
}
for(int i = 1; i <= m; i ++) printf("%d\n", ans[i]);

}

posted @ 2022-04-26 22:59  牛佳文  阅读(48)  评论(0编辑  收藏  举报