1. 程式人生 > 其它 >[Violet]蒲公英

[Violet]蒲公英

[Violet]蒲公英

強制線上求區間眾數。

思路

與一些分塊題不同,本題並沒有在塊內插入其他東西進行維護,最樸素的分塊。類似【作詩】的預處理,預先處理出每個數出現的塊字尾和(字首和應該也沒有問題),以及塊間的眾數。對於[l,r]位於的塊是挨著或在同一塊的情況,直接暴力處理(挨著的不太好處理),其餘的按照分塊的正常思路進行。顯然,[l,r]的眾數一定是整塊的眾數或者散塊中出現的數。注意細節:要輸出的是離散化前的編號,以及這裡是字尾和,別還原成了字首和。

程式碼

memset又一次拖慢近5倍。

inline void INIT()
{
	len = sqrt(n);t = n / len;
	for(int i = 1;i <= t;i++){
		L[i] = (i - 1) * len + 1;
		R[i] = i * len;
	}
	R[t] = n;
	block[n + 1] = n + 1;
	for(int i = 1;i <= t;i++)
	   for(int j = L[i];j <= R[i];j++) block[j] = i;
	for(int i = 1;i <= t;i++){
		int mx = 0;
		for(int j = L[i];j <= n;j++){
			cnt[i][a[j]]++;
			if(cnt[i][mx] < cnt[i][a[j]] || (cnt[i][mx] == cnt[i][a[j]] && a[j] < mx)) mx = a[j];
			if(block[j] != block[j + 1]) res[i][block[j]] = mx;
		}
	}	
}

signed main()
{
	n = read();m = read();
	for(int i = 1;i <= n;i++) a[i] = read(),b[i] = a[i];
	sort(b + 1,b + 1 + n);
	tot = unique(b + 1,b + 1 + n) - b - 1;
	for(int i = 1;i <= n;i++) a[i] = lower_bound(b + 1,b + 1 + tot,a[i]) - b;
	INIT();
	
	while(m--)
	{
		LL l,r;ans = 0;
		scanf("%lld%lld",&l,&r);
		l = (l + lstans - 1) % n + 1,r = (r + lstans - 1) % n + 1;
		if(l > r) swap(l,r);
		if(block[l] + 1 >= block[r]){
			for(int i = l;i <= r;i++){
				num[a[i]]++;
				if(num[ans] < num[a[i]] || (num[ans] == num[a[i]] && a[i] < ans)) ans = a[i];
			}
			lstans = b[ans];
			write(lstans);putchar('\n');
			for(int i = l;i <= r;i++) num[a[i]]--;
			
			continue;
		}
		ans = res[block[l] + 1][block[r] - 1];
		int all = cnt[block[l] + 1][ans] - cnt[block[r]][ans];
		for(int i = l;i <= R[block[l]];i++){
			num[a[i]]++;
			if(num[ans] + all < num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] || 
			  (num[ans] + all == num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] && a[i] < ans)) 
			    ans = a[i],all = cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]];
		}
		for(int i = L[block[r]];i <= r;i++){
			num[a[i]]++;
			if(num[ans] + all < num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] || 
			  (num[ans] + all == num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] && a[i] < ans)) 
			    ans = a[i],all = cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]];
		}
		lstans = b[ans];
		write(lstans);putchar('\n');
		
		for(int i = l;i <= R[block[l]];i++) num[a[i]]--;
		for(int i = L[block[r]];i <= r;i++) num[a[i]]--;
	}
	return 0;
}
艱難困苦,玉汝於成