zoukankan      html  css  js  c++  java
  • BZOJ_3489_ A simple rmq problem_KDTree

    BZOJ_3489_ A simple rmq problem_KDTree

    Description

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

    Input

    第一行为两个整数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

     

    Output

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

     

    Sample Input

    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

    Sample Output

    4
    10
    10
    0
    0
    10
    0
    4
    0
    4

    HINT

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

    2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测


    设ai上一次出现的位置为pre[i],下一次出现的位置为nxt[i],则我们需要找一个ai最大的点,使得l<=i<=r,pre[i]<l,nxt[i]>r。

    使用三维KDTree即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    #define N 100050
    int ch[N][2],mx[N][3],mn[N][3],root,now,mxv[N],n,ans,m,tt[N];
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define _min(x,y) ((x)<(y)?(x):(y))
    #define _max(x,y) ((x)>(y)?(x):(y))
    #define _(x) (x==2?0:x+1)
    struct Point {
    	int p[3],v;
    	bool operator < (const Point &x) const {
    		int t=_(now);
    		if(p[now]==x.p[now]&&p[t]==x.p[t]) return p[_(t)]<x.p[_(t)];
    		if(p[now]==x.p[now]) return p[t]<x.p[t];
    		return p[now]<x.p[now];
    	}
    }a[N];
    void pushup(int p,int x) {
    	int i;
    	for(i=0;i<3;i++) {
    		mn[p][i]=_min(mn[p][i],mn[x][i]);
    		mx[p][i]=_max(mx[p][i],mx[x][i]);
    	}
    	mxv[p]=_max(mxv[p],mxv[x]);
    }
    int build(int l,int r,int type) {
    	int mid=(l+r)>>1; now=type;
    	nth_element(a+l,a+mid,a+r+1);
    	int i;
    	for(i=0;i<3;i++) mn[mid][i]=mx[mid][i]=a[mid].p[i];
    	mxv[mid]=a[mid].v;
    	if(l<mid) ch[mid][0]=build(l,mid-1,_(type)),pushup(mid,ch[mid][0]);
    	if(r>mid) ch[mid][1]=build(mid+1,r,_(type)),pushup(mid,ch[mid][1]);
    	return mid;
    }
    void query(int l,int r,int p) {
    	if(!p||mxv[p]<=ans||mx[p][0]<l||mn[p][0]>r||mn[p][1]>=l||mx[p][2]<=r) return ;
    	if(a[p].p[0]>=l&&a[p].p[0]<=r&&a[p].p[1]<l&&a[p].p[2]>r) ans=_max(ans,a[p].v);
    	query(l,r,ls); query(l,r,rs);
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	int i,x,y;
    	for(i=1;i<=n;i++) {
    		scanf("%d",&x);
    		a[i].p[0]=i;
    		a[i].p[1]=tt[x];
    		a[tt[x]].p[2]=i;
    		tt[x]=i;
    		a[i].v=x;
    	}
    	for(i=1;i<=n;i++) if(!a[i].p[2]) a[i].p[2]=n+1;
    	root=build(1,n,0);
    	for(i=1;i<=m;i++) {
    		scanf("%d%d",&x,&y);
    		int l=min((x+ans)%n+1,(y+ans)%n+1),r=max((x+ans)%n+1,(y+ans)%n+1);
    		ans=0; query(l,r,root);
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    iOS 10 的杂碎资料
    MAC SVN Merge 操作
    iOS中AFNetworking2.0和AFNetworking3.0 的HTTPS的配置
    从字符串中获取指定字符内的内容
    判断是否是是全汉字、全字母、全数字、数字和字母等
    解析URL 获取某一个参数值
    长按TextField或TextView显示中文的粘贴复制
    TextField和TextView的限制输入长度
    抢购、距活动结束,剩余时间倒计时。
    Cell右滑 多个编辑选项栏
  • 原文地址:https://www.cnblogs.com/suika/p/9279106.html
Copyright © 2011-2022 走看看