[BZOJ3489]A simple rmq problem

description

给出一个长度为(n)的序列({a_i}),给出(M)个询问:在([l,r])之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出(0)
强制在线。

data range

[nle 10^5,mle 2 imes 10^5,1le a_ile n ]

solution

根据[APIO2018]新家的套路,找到其前驱(pre_i)和后继(nxt_i),于是有三元组((i,pre_i,nxt_i))

那么查询([l,r])就是查询(([l,r],[0,l-1],[r+1,n+1]))

然后就是三维偏序了?

然后它就变成了一道(kd-tree)剪枝好题

发现自己的(kd-tree)原来这么丑

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define Cpy(x,y) (memcpy(x,y,sizeof(x)))
#define Set(x,y) (memset(x,y,sizeof(x)))
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=200010;
const int M=205;
const dd pi=acos(-1);
const int inf=2147483647;
const ll INF=1e18+1;
const ll P=100000;
il int read(){
	RG int data=0,w=1;RG char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch<='9'&&ch>='0')data=(data<<3)+(data<<1)+(ch^48),ch=getchar();
	return data*w;
}

il void file(){
	srand(time(NULL)+rand());
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
}

int n,m,rt,cd,ans,o[N],a[N],nxt[3]={1,2,0};
struct node{int d[3],v;}p[N];
bool operator <(node a,node b){return a.d[cd]<b.d[cd];}
struct kdnode{int d[3],mx[3],mn[3],s[2],val,Mx;}t[N];
il void update(RG int i){
	for(RG int k=0;k<=2;k++){
		t[i].mx[k]=t[i].mn[k]=t[i].d[k];
		if(t[i].s[0]){
			t[i].mx[k]=max(t[i].mx[k],t[t[i].s[0]].mx[k]);
			t[i].mn[k]=min(t[i].mn[k],t[t[i].s[0]].mn[k]);
		}
		if(t[i].s[1]){
			t[i].mx[k]=max(t[i].mx[k],t[t[i].s[1]].mx[k]);
			t[i].mn[k]=min(t[i].mn[k],t[t[i].s[1]].mn[k]);
		}
	}
	t[i].Mx=max(t[i].val,max(t[t[i].s[0]].Mx,t[t[i].s[1]].Mx));
}
#define mid ((l+r)>>1)
int build(int l,int r,int D){
	if(l>r)return 0;
	cd=D;nth_element(p+l,p+mid,p+r+1);
	Cpy(t[mid].d,p[mid].d);t[mid].val=p[mid].v;
	t[mid].s[0]=build(l,mid-1,nxt[D]);
	t[mid].s[1]=build(mid+1,r,nxt[D]);
	update(mid);return mid;
}
#define cmax(x,y) (x=x>y?x:y)
#define ckm(dd) (mn[dd]<=t[i].mn[dd]&&t[i].mx[dd]<=mx[dd])
#define ckd(dd) (mn[dd]<=t[i].d[dd]&&t[i].d[dd]<=mx[dd])
#define cke(dd) (mn[dd]>t[i].mx[dd]||mx[dd]<t[i].mn[dd])
int mn[3],mx[3];
void query(int i,int D){
	if(t[i].Mx<=ans||cke(0)||cke(1)||cke(2))return;//这是主要的剪枝。
	if(ckm(2)&&ckm(1)&&ckm(0)){cmax(ans,t[i].Mx);return;}
	if(ckd(2)&&ckd(1)&&ckd(0))cmax(ans,t[i].val);
	if(mn[D]<=t[t[i].s[0]].mx[D])query(t[i].s[0],nxt[D]);
	if(t[t[i].s[1]].mn[D]<=mx[D])query(t[i].s[1],nxt[D]);
}
int main()
{
	n=read();m=read();
	for(RG int i=1;i<=n;i++)p[i].v=a[i]=read(),p[i].d[0]=i;
	Set(o,0);
	for(RG int i=1;i<=n;i++)p[i].d[1]=o[a[i]],o[a[i]]=i;
	for(RG int i=1;i<=n;i++)o[i]=n+1;
	for(RG int i=n;i;i--)p[i].d[2]=o[a[i]],o[a[i]]=i;
	rt=build(1,n,0);
	for(RG int i=1,l,r;i<=m;i++){
		l=(read()+ans)%n+1;r=(read()+ans)%n+1;if(l>r)swap(l,r);
		mn[0]=l;mx[0]=r;mn[1]=0;mx[1]=l-1;mn[2]=r+1;mx[2]=n+1;
		ans=0;query(rt,0);
		printf("%d
",ans);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/cjfdf/p/9651453.html