萌新分块全TLE求教,悬赏关注
  • 板块P4135 作诗
  • 楼主Kalium
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/8/20 11:25
  • 上次更新2023/11/3 02:30:03
查看原帖
萌新分块全TLE求教,悬赏关注
328170
Kalium楼主2023/8/20 11:25

如题

思路和P4168蒲公英差不多

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

const int N = 1e5 + 7;

using namespace std;

int n, c, m, blo, tot, ans;

int a[N], b[N], tong[N], flag[N];

int f[407][407], s[407][N];//第i块到第j块中的偶数个数,前i块中a[j]出现的次数

inline int block(int x) {
	return (x - 1) / blo + 1; 
}

inline void init() {
	tot = (n - 1) / blo + 1;
	
	for (int i = 1; i <= tot; ++ i) {
		int down = blo * (i - 1) + 1, up = std :: min(blo * i, n);
		
		for (int j = down; j <= up; ++ j) s[i][a[j]] ++;
		for (int j = 1; j <= c; ++ j) s[i][j] += s[i - 1][j];
	}
	
		for (int i = 1; i <= tot; ++ i) {
		for (int j = i; j <= tot; ++ j) {
			int down = blo * (j - 1) + 1, up = std :: min(blo * j, n);
			
			f[i][j] = f[i][j - 1];
			
			for (int k = down; k <= up; ++ k) {
				int del = s[j][a[k]] - s[i - 1][a[k]];
				
				if (! (del & 1)) f[i][j] = f[i][j - 1] + 1;
			}
		}
	}
}

inline int query(int l, int r) {
	memset(tong, 0, sizeof(tong));
	memset(flag, 0, sizeof(flag));
	
	int res = 0;
	int bl = block(l), br = block(r);
	
	//cout << bl << " " << br << endl;
	
	if (br - bl <= 1) {
		for (int i = l; i <= r; ++ i) tong[a[i]] ++;
		
		for (int i = l; i <= r; ++ i)
			if (! (tong[a[i]] & 1) && ! flag[a[i]]) res ++, flag[a[i]] = 1;
		
		return res;
	}
	
	for (int i = l; i <= blo * bl; ++ i) tong[a[i]] ++;
	for (int i = blo * (br - 1) + 1; i <= r; ++ i) tong[a[i]] ++;
	
	res = f[bl + 1][br - 1];
	
	for (int i = l; i <= blo * bl; ++ i) {
		if (flag[a[i]]) continue;
		
		flag[a[i]] = 1;
		
		int del = s[br - 1][a[i]] - s[bl][a[i]];
		int num = tong[a[i]] + del;
		
		if (! (num & 1) && ((del & 1) || ! del) && num) res ++;
		if ((num & 1) && del && ! (del & 1)) res --;
		 
	}
	
	for (int i = bl * (br - 1) + 1; i <= r; ++ i) {
		if (flag[a[i]]) continue;
		
		flag[a[i]] = 1;
		
		int del = s[br - 1][a[i]] - s[bl][a[i]];
		int num = tong[a[i]] + del;
		
		if (! (num & 1) && ((del & 1) || ! del) && num) res ++;
		if ((num & 1) && del && ! (del & 1)) res --;
	}
	
	return res;
}

int main() {
	scanf("%d%d%d", &n, &c, &m);
	
	c = 0;
	blo = sqrt(n);
	
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &a[i]);
		
		c = std :: max(c, a[i]);
	}
	
	init();
	
/*	cout << tot << endl;
	
	for (int i = 1; i <= tot; ++ i) {
		for (int j = 1; j <= c; ++ j)
			cout << std :: min(blo * i, n) << " " << s[i][j] << endl;
	}
	
	for (int i = 1; i <= tot; ++ i) {
		for (int j = i; j <= tot; ++ j)
			cout << blo * (i - 1) + 1 << " " << std :: min(blo * j, n) << " " << f[i][j] << endl;
	}*/

	for (int i = 1; i <= m; ++ i) {
		int l, r;
		
		scanf("%d%d", &l, &r);

		l = (l + ans) % n + 1, r = (r + ans) % n + 1;
		
		if (l > r) std :: swap(l, r);
		
		printf("%d\n", ans = query(l, r));
	}
}
2023/8/20 11:25
加载中...