回滚莫队22pts求助(有代码注释)
查看原帖
回滚莫队22pts求助(有代码注释)
373938
wowwowwow楼主2024/5/14 21:50

基本参照第一篇题解。已经写了两天了。讨论区也都翻过了真的调不出来

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

const int N = 2e5 + 10;

int n, m, block, last[N], num[N], a[N], br[N], ma[N], fir[N], clear[N], ANS[N];

struct node{
	int l, r, id;
}q[N];

bool cmp(node x, node y){
	if(x.l / block != y.l / block) return x.l / block < y.l / block;
	return x.r < y.r;
}

void calc(int L, int R, int id){
	int maxn = 0;
	for(int i = L; i <= R; i++) last[a[i]] = 0;
	for(int i = L; i <= R; i++){
		if(!last[a[i]]) last[a[i]] = i;
		
		maxn = max(maxn, i - last[a[i]]);
	}
	ANS[id] = maxn;
}

signed main(){
	//回滚莫队:正常莫队+l回滚,并记录初始值
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]), num[i] = a[i];
	sort(num + 1, num + n + 1);
	int tot = unique(num + 1, num + n + 1) - num - 1;
	for(int i = 1; i <= n; i++){
		a[i] = lower_bound(num + 1, num + tot + 1, a[i]) - num;
	}
	//正常离散化()
	
	scanf("%d", &m);
	for(int i = 1; i <= m; i++){
		scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i;
	}
	block = sqrt(n); //块数。这里我直接用i / block表示i所属的块 
	sort(q + 1, q + m + 1, cmp);
	for(int i = 1; i <= n; i++) //这个块的右端点 
		br[i / block] = i;
	int l = 0, r = 0, ans = 0, cnt = 0;
	//先移动r,并记录此时的状态,l挪至原位时则恢复 
	for(int i = 1, j = -1; i <= m; i++){ //第i个询问,第j个块
	
		if(q[i].l / block > j){
			for(int i = 1; i <= cnt; i++) ma[clear[i]] = 0, fir[clear[i]] = 0, clear[i] = 0;
			cnt = 0;
			j = q[i].l / block;
			l = br[j] + 1; r = l - 1;
		}
		if(q[i].l / block  == q[i].r / block){ //在同个块,暴力 
			calc(q[i].l, q[i].r, q[i].id);
		}
		else{
			while(r < q[i].r){
				r++;
				if(!fir[a[r]]) fir[a[r]] = r;
				clear[++cnt] = a[r];
				ma[a[r]] = r;
				ans = max(ans, ma[a[r]] - fir[a[r]]);
 			}
 			int tp = ans; //记录只考虑右边区间的ans
//			printf("kk%d\n", tp);
 			while(l > q[i].l){
 				l--;
 				if(ma[a[l]]) ans = max(ma[a[l]] - l, ans);
 				else ma[a[l]] = l; 
 			}
// 			for(int i = 1; i <= 4; i++) printf("kkdy%d ", ma[i]);
// 			printf("\n");
// 			printf("kkdy%d %d %d %d\n", i, j, l, r);
 			ANS[q[i].id] = ans;
 			ans = tp;
 			while(l <= br[j]){
 				if(ma[a[l]] == l) ma[a[l]] = 0;
				l++;
			}
		}
	}
	for(int i = 1; i <= m; i++) printf("%d\n", ANS[i]);
	return 0;
}
2024/5/14 21:50
加载中...