[BZOJ3489]A simple rmq problem

[BZOJ3489]A simple rmq problem

试题描述

因为是OJ上的题,就简单点好了。给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。

输入

第一行为两个整数N,MM是询问数,N是序列的长度(N<=100000M<=200000)

第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N

再下面M行,每行两个整数xy

询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<)

l=min(x+lastans)mod n+1,(y+lastansmod n+1);

r=max(x+lastans)mod n+1,(y+lastansmod n+1);

Lastans表示上一个询问的答案,一开始lastans0

注意出题人为了方便,input的第二行最后多了个空格。

输出

一共M行,每行给出每个询问的答案。

输入示例

10 10
6 4 9 10 9 10 9 4 10 4 
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9

输出示例

4
10
10
0
0
10
0
4
0
4

数据规模及约定

见“输入

题解

预处理一下,对于每一个数,将离它最近的与它相等的数的位置求出来,左边的位置表示成 pre[i],右边的位置表示成 nxt[i],如果没有左边的相同的数字则 pre[i] = 0,若没有右边的相同的数字则 nxt[i] = n + 1. 那么第 i 个数在空间中可以表示成 (i, pre[i], nxt[i]) 这个点,当一个询问 [L, R] 到来时,就是查询所有满足 L <= i <= R & pre[i] < L & R < nxt[i] 的最大点权。不难发现这是一个空间中的长方体,可以用树套树套树解决。

当然只有区间查询的 kd 树还是有复杂度保证的。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <ctime>
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 100010
#define oo 2147483647
int n, m, root, lc[maxn], rc[maxn], Cur, A[maxn], now[maxn];
struct Node {
	int x[3], mx[3], mn[3], val, maxv;
	bool operator < (const Node& t) const { return x[Cur] < t.x[Cur]; }
} ns[maxn];

void maintain(int o) {
	int l = lc[o], r = rc[o];
	for(int i = 0; i < 3; i++) {
		ns[o].mx[i] = max(max(ns[l].mx[i], ns[r].mx[i]), ns[o].x[i]);
		ns[o].mn[i] = min(min(ns[l].mn[i], ns[r].mn[i]), ns[o].x[i]);
	}
	ns[o].maxv = max(max(ns[l].maxv, ns[r].maxv), ns[o].val);
	return ;
}
void build(int& o, int L, int R, int cur) {
	if(L > R){ o = 0; return ; }
	int M = L + R >> 1; o = M;
	Cur = cur; nth_element(ns + L, ns + M, ns + R + 1);
	build(lc[o], L, M - 1, (cur + 1) % 3); build(rc[o], M + 1, R, (cur + 1) % 3);
	maintain(o);
	return ;
}
int ql, qr;
bool all(int o) { return ql <= ns[o].mn[0] && ns[o].mx[0] <= qr && ns[o].mx[1] < ql && ns[o].mn[2] > qr; }
bool has(int o) { return ql <= ns[o].mx[0] && ns[o].mn[0] <= qr && ns[o].mn[1] < ql && ns[o].mx[2] > qr; }
int query(int o) {
	if(!o) return 0;
	int ans = 0, l = lc[o], r = rc[o];
	if(ns[l].maxv > ns[r].maxv) {
		if(ns[l].maxv > ans) {
			if(all(l)) ans = max(ans, ns[l].maxv);
			else if(has(l)) ans = max(ans, query(l));
		}
		if(ns[r].maxv > ans) {
			if(all(r)) ans = max(ans, ns[r].maxv);
			else if(has(r)) ans = max(ans, query(r));
		}
	}
	else {
		if(ns[r].maxv > ans) {
			if(all(r)) ans = max(ans, ns[r].maxv);
			else if(has(r)) ans = max(ans, query(r));
		}
		if(ns[l].maxv > ans) {
			if(all(l)) ans = max(ans, ns[l].maxv);
			else if(has(l)) ans = max(ans, query(l));
		}
	}
	int x = ns[o].x[0], pre = ns[o].x[1], nxt = ns[o].x[2];
	if(ql <= x && x <= qr && pre < ql && nxt > qr) ans = max(ans, ns[o].val);
	return ans;
}

int main() {
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
//	int clo = clock();
	ns[0].mx[0] = ns[0].mx[1] = ns[0].mx[2] = -oo;
	ns[0].mn[0] = ns[0].mn[1] = ns[0].mn[2] = oo;
	ns[0].maxv = -oo;
	n = read(); m = read();
	for(int i = 1; i <= n; i++) {
		A[i] = read();
		ns[i].x[0] = i; ns[i].x[1] = now[A[i]];
		now[A[i]] = i;
	}
	for(int i = 1; i <= n; i++) now[i] = n+1;
	for(int i = n; i; i--) {
		ns[i].x[2] = now[A[i]]; ns[i].maxv = ns[i].val = A[i];
		now[A[i]] = i;
	}
	
	build(root, 1, n, 0);
	int lastans = 0;
	while(m--) {
		int x = read(), y = read();
		ql = min((x + lastans) % n + 1, (y + lastans) % n + 1);
		qr = max((x + lastans) % n + 1, (y + lastans) % n + 1);
		lastans = query(root);
		printf("%d\n", lastans);
	}
//	printf("%d\n", clock() - clo);
	
	return 0;
}

 

posted @ 2016-07-20 16:38  xjr01  阅读(277)  评论(0编辑  收藏  举报