[BZOJ2724][Violet 6]蒲公英

[BZOJ2724][Violet 6]蒲公英

试题描述

输入

修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

输出

输入示例

6 3
1 2 3 2 1 2
1 5
3 6
1 5

输出示例

1
2
1

数据规模及约定

修正下:

n <= 40000, m <= 50000

题解

分块,先预处理出 f[i][j] 表示第 i 块到第 j 块的众数,枚举起点 i 然后扫一遍就好了。

其次是询问,对于一个询问 [ql, qr],其中 ql 属于块 l,qr 属于块 r,众数要么是 f[l+1][r-1],要么是不完整块中的数,所以我们需要搞一个 calc(l, r, x) 功能,表示询问 [l, r] 中 x 出现的次数,有了这个功能后就可以做到把答案初始设为 f[l+1][r-1](O(1)),然后 O(sqrt(n)) 暴力枚举不完整块中的数,如果出现次数比当前的多,就更新答案。

这个 calc() 函数可以这样搞:把所有数离散,每个数的位置记下来,然后当询问 calc(l, r, x) 在 x 的位置序列上二分一下就可以计算了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
    if(Head == Tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        Tail = (Head = buffer) + l;
    }
    return *Head++;
}
int read() {
    int x = 0, f = 1; char c = Getchar();
    while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    return x * f;
}

#define maxn 40010
#define maxq 210
int n, m, num[maxn], A[maxn], st[maxq], en[maxq], bl[maxn], cntb, f[maxq][maxq], cntn[maxn];

vector <int> pos[maxn];
int calc(int l, int r, int x) {
	return upper_bound(pos[x].begin(), pos[x].end(), r) - lower_bound(pos[x].begin(), pos[x].end(), l);
}
int query(int ql, int qr) {
	int l = bl[ql], r = bl[qr];
	if(r - l <= 1) {
		int ans = A[ql], mx = calc(ql, qr, ans);
		for(int i = ql + 1; i <= qr; i++) {
			int tmp = calc(ql, qr, A[i]);
			if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
		}
		return ans;
	}
	int ans = f[l+1][r-1], mx = calc(ql, qr, ans);
	for(int i = ql; i <= en[l]; i++) {
		int tmp = calc(ql, qr, A[i]);
		if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
	}
	for(int i = st[r]; i <= qr; i++) {
		int tmp = calc(ql, qr, A[i]);
		if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
	}
	return ans;
}

int main() {
	n = read(); m = read();
	int siz = (int)sqrt(n + .5);
	for(int i = 1; i <= n; i++) {
		num[i] = A[i] = read();
		int p = (i - 1) / siz + 1; cntb = p;
		if(!st[p]) st[p] = i;
		en[p] = i;
		bl[i] = p;
	}
	
	sort(num + 1, num + n + 1);
	for(int i = 1; i <= n; i++) A[i] = lower_bound(num + 1, num + n + 1, A[i]) - num;
	for(int i = 1; i <= cntb; i++) {
		memset(cntn, 0, sizeof(cntn));
		for(int j = st[i]; j <= n; j++) {
			cntn[A[j]]++;
			int r = bl[j];
			if(r > i && !f[i][r]) f[i][r] = f[i][r-1];
			if(!f[i][r] || cntn[f[i][r]] < cntn[A[j]] || (cntn[f[i][r]] == cntn[A[j]] && f[i][r] > A[j]))
				f[i][r] = A[j];
		}
	}
	for(int i = 1; i <= n; i++) pos[A[i]].push_back(i);
	
	int x = 0;
	while(m--) {
		int l = (read() + x - 1) % n + 1, r = (read() + x - 1) % n + 1;
		if(l > r) swap(l, r);
		int tmp = query(l, r);
		printf("%d\n", num[tmp]);
		x = num[tmp];
	}
	
	return 0;
}

 

posted @ 2016-08-22 15:29  xjr01  阅读(302)  评论(0编辑  收藏  举报