KD_tree 板子

来源:互联网 发布:sqlserver 大数据导入 编辑:程序博客网 时间:2024/06/12 01:35

例题:3489: A simple rmq problem

在[l,r]内找只出现一次的,最大的数
用pre记录每个位置的数上次出现位置,nex记录下次出现位置
一个位置i的值在[l,r]内只出现一次,那么 l <= i <= r , prei< l, nexi>r,所以给一个点三维坐标(i,prei,nexi),询问时用kd-tree找(l~r,0~l-1,r+1~n+1)里最大的值

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;int read(){    char c; int x;    while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';    return x;}void up(int &x,const int y){if(x<y)x=y;}void down(int &x,const int y){if(x>y)x=y;}const int maxn = 110000;const int maxd = 3;struct Kd_tree{    int s,c,pos[maxd],u[maxd],d[maxd],lc,rc;}kd[maxn]; int root;int n,m;int cmp_d;bool cmp(const Kd_tree &x,const Kd_tree &y) { return x.pos[cmp_d]<y.pos[cmp_d]; }void push_up(const int &x){    const int lc=kd[x].lc,rc=kd[x].rc;    if(lc)    {        for(int i=0;i<maxd;i++)            up(kd[x].u[i],kd[lc].u[i]),            down(kd[x].d[i],kd[lc].d[i]);        up(kd[x].c,kd[lc].c);    }    if(rc)    {        for(int i=0;i<maxd;i++)            up(kd[x].u[i],kd[rc].u[i]),            down(kd[x].d[i],kd[rc].d[i]);        up(kd[x].c,kd[rc].c);    }}int Build(int l,int r,int D){    cmp_d=D; int mid=(l+r)>>1;    std::nth_element(kd+l,kd+mid,kd+r+1,cmp);    for(int i=0;i<maxd;i++)        kd[mid].u[i]=kd[mid].d[i]=kd[mid].pos[i];    kd[mid].c=kd[mid].s; kd[mid].lc=kd[mid].rc=0;    if(l==r) return mid;    if(l!=mid) kd[mid].lc=Build(l,mid-1,(D+1)%3);    if(mid!=r) kd[mid].rc=Build(mid+1,r,(D+1)%3);    push_up(mid);    return mid;}int Pu[maxd],Pd[maxn];int Cal(const int x){    if(!x) return 0;    for(int i=0;i<maxd;i++)        if(kd[x].d[i]>Pu[i]||kd[x].u[i]<Pd[i]) return 0;    return kd[x].c;}int Ask(const int x){    for(int i=0;i<maxd;i++)        if(kd[x].d[i]>Pu[i]||kd[x].u[i]<Pd[i]) return 0;    bool flag=true;    for(int i=0;i<maxd;i++)        if(!(Pd[i]<=kd[x].d[i]&&kd[x].u[i]<=Pu[i])) {flag=false; break;}    if(flag) return kd[x].c;    int re=0;    flag=true;    for(int i=0;i<maxd;i++)        if(!(Pd[i]<=kd[x].pos[i]&&kd[x].pos[i]<=Pu[i])) {flag=false; break;}    if(flag) re=kd[x].s;    int k1=Cal(kd[x].lc),k2=Cal(kd[x].rc);    if(k1>k2)    {        if(k1>re) up(re,Ask(kd[x].lc));        if(k2>re) up(re,Ask(kd[x].rc));    }    else    {        if(k2>re) up(re,Ask(kd[x].rc));        if(k1>re) up(re,Ask(kd[x].lc));    }    return re;}int Posi[maxn];int a[maxn],pre[maxn],nex[maxn];int main(){    n=read(),m=read();    for(int i=1;i<=n;i++) a[i]=read();    for(int i=1;i<=n;i++)        pre[i]=Posi[a[i]],Posi[a[i]]=i;    for(int i=1;i<=n;i++) Posi[i]=n+1;    for(int i=n;i>=1;i--)        nex[i]=Posi[a[i]],Posi[a[i]]=i;    for(int i=1;i<=n;i++)        kd[i].s=a[i],kd[i].pos[0]=i,kd[i].pos[1]=pre[i],kd[i].pos[2]=nex[i];    Build(1,n,0); root=(1+n)>>1;    int ans=0;    while(m--)    {        int x=(read()+ans)%n+1,y=(read()+ans)%n+1;        int l=min(x,y),r=max(x,y);        Pd[0]=l,Pu[0]=r;        Pd[1]=0,Pu[1]=l-1;        Pd[2]=r+1,Pu[2]=n+1;        printf("%d\n",ans=Ask(root));    }    return 0;}
1 0
原创粉丝点击