回滚莫队 88 pts TLE 求调!!!
查看原帖
回滚莫队 88 pts TLE 求调!!!
363036
chlchl楼主2023/2/15 14:03

块长调过很多次了……

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

const int N = 2e5 + 10;
int n, m, a[N], b[N], ear[N], late[N];
int blk, tot, bel[N];
int ret[N], clean[N];
struct event{
	int l, r, id;
	bool operator < (const event &p) const {
		if(bel[l] != bel[p.l])
			return bel[l] < bel[p.l];
		return r < p.r;
	}
} q[N];

int baoli(int l, int r){
	int lear[N] = {0}, res = 0;
//	for(int i=l;i<=r;i++)
//		ear[a[i]] = 0;
	for(int i=l;i<=r;i++){
		if(!lear[a[i]])
			lear[a[i]] = i;
		res = max(res, i - lear[a[i]]);
	}
	return res;
}

int main(){
	scanf("%d", &n);
	for(int i=1;i<=n;i++)
		scanf("%d", &a[i]), b[i] = a[i];
	sort(b + 1, b + 1 + n);
	int len = unique(b + 1, b + 1 + n) - b - 1;
	for(int i=1;i<=n;i++)
		a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b;
	scanf("%d", &m);
	for(int i=1;i<=m;i++)
		scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
	blk = 233;
	for(int i=1;i<=n;i++)
		bel[i] = (i - 1) / blk + 1;//分块基础 
	sort(q + 1, q + 1 + m);
	int now = 1;//当前处理到第几个询问 
	for(int j=1;j<=bel[n];j++){//枚举每个块 
		int tmp = 0, br = min(n, j * blk);//br 块的右端点 
		int l = br + 1, r = l - 1, ans = 0;//l, r 左右指针,ans 当前答案 
		while(bel[q[now].l] == j){//左端点在同一块内一起处理
			if(bel[q[now].l] == bel[q[now].r]){
				ret[q[now].id] = baoli(q[now].l, q[now].r);
				++now;
				continue;
			}
			while(r < q[now].r){
				++r;
				late[a[r]] = r;
				if(!ear[a[r]])
					ear[a[r]] = r, clean[++tmp] = a[r];
				ans = max(ans, r - ear[a[r]]);
			}
			int ansr = ans;//右端点单调递增,因此答案不用清空,左端点则需要清空 
			while(l > q[now].l){
				--l;//不用更新 ear 数组,因为后面再也没有右端点右移的操作了,左端点自己就是 ear[a[l]] 
				if(!late[a[l]])
					late[a[l]] = l;
				ans = max(ans, late[a[l]] - l);
			}
			ret[q[now].id] = ans;//这个询问已经处理完了 
			while(l <= br){
				if(late[a[l]] == l)//如果最开始的数在左边出现,直接清零即可,不用看后一次的位置
					late[a[l]] = 0;//因为左端点最后会到块的右端点
				l++;
			}
			++now, ans = ansr;//继承右端点的答案,这样就消除了左端点的影响
		}
		for(int i=1;i<=tmp;i++)
			late[clean[i]] = ear[clean[i]] = 0;//下一个块到来时,这一块右端点的答案就需要被清空
	}
	for(int i=1;i<=m;i++)
		printf("%d\n", ret[i]);
	return 0;
}
2023/2/15 14:03
加载中...