您的位置:首页 > 其它

3489: A simple rmq problem K-D tree

2016-03-14 06:21 344 查看
K-D树解决一些传统的序列问题,详细解法可参见任之洲《k-d tree在传统OI数据结构题中的应用》

用lastxlast_x表示xx上次出现的位置,nextxnext_x表示xx下次出现的位置,所以要求的就是满足l≤i≤r,lastai<l,nextai>rl\leq i \leq r,last_{a_i}r的aia_i的最大值,可以看作是三维平面中的点,然后用三维k-d tree解决极值问题。

复杂度O(mn23)O(mn^{\frac{2}{3}})

[code]#include<iostream>
#include<cstdio>
#include<algorithm>
#define inf 1000000007
#define N 100005
using namespace std;
struct node 
{
    int d[3],mn[3],mx[3];
    int v,mv;
};
node tree
;
int ls
,rs
,pre
;
int n,m,ans,root,L,R,D;
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool operator<(node a,node b)
{
    return a.d[D]<b.d[D];
}
inline void pushup(int k)
{
    for (int i=0;i<=2;i++)
    {
        tree[k].mn[i]=min(tree[k].d[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i]));
        tree[k].mx[i]=max(tree[k].d[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i]));
    }
    tree[k].mv=max(tree[k].v,max(tree[ls[k]].mv,tree[rs[k]].mv));
}
void build(int &k,int l,int r,int dir)
{
    int mid=l+r>>1; k=mid; D=dir;
    nth_element(tree+l,tree+mid,tree+r+1);
    if (l<mid) build(ls[k],l,mid-1,(dir+1)%3);
    if (r>mid) build(rs[k],mid+1,r,(dir+1)%3);
    pushup(k);
}
inline bool check(int k)
{
    if (!k) return 0;
    if (tree[k].mn[1]>=L||tree[k].mx[2]<=R||tree[k].mx[0]<L||tree[k].mn[0]>R) return 0;
    return 1;
}
void query(int k)
{
    if (!k) return;
    if (tree[k].mn[0]>=L&&tree[k].mx[0]<=R&&tree[k].mx[1]<L&&tree[k].mn[2]>R) 
    {
        ans=max(ans,tree[k].mv);
        return;
    }
    if (tree[k].d[0]>=L&&tree[k].d[0]<=R&&tree[k].d[1]<L&&tree[k].d[2]>R)
        ans=max(ans,tree[k].v);
    if (tree[ls[k]].mv>tree[rs[k]].mv)
    {
        if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]);
        if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]);
    }
    else
    {
        if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]);
        if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]);
    }
}
int main()
{
    for (int i=0;i<=2;i++)
        tree[0].mx[i]=-inf,tree[0].mn[i]=inf;
    n=read(); m=read();
    for (int i=1;i<=n;i++)
    {
        int x=read();
        tree[i].d[0]=i; tree[i].d[2]=n+1; tree[i].v=tree[i].mv=x;
        if (pre[x]) tree[i].d[1]=pre[x],tree[pre[x]].d[2]=i;
        pre[x]=i;
    }
    build(root,1,n,0);
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        L=min((x+ans)%n+1,(y+ans)%n+1);
        R=max((x+ans)%n+1,(y+ans)%n+1);
        ans=0;
        query(root);
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: