1. 程式人生 > >【bzoj3489】A simple rmq problem

【bzoj3489】A simple rmq problem

str 順序 ring n+1 namespace http names 需要 update

Portal -->bzoj3489

Solution

  最近計劃智力康復qwq(話說這題一年前剛剛開始寫樹套樹的時候感覺好難啊qwq現在看其實還好也算是有進步的嘛!)

  比較重要的一步是,要將“在\([l,r]\)中只出現一次”這個條件轉化成"\(nxt[x]>r\)&&\(pre[x]<l\)",其中\(nxt[x]\)表示下一個出現位置\(x\)的數的位置,\(pre[x]\)表示前一個

  然後我們就發現其實是有三個限制:

1、\(pre[x]<l\)

2、\(nxt[x]>r\)

3、最大

  那所以我們用兩棵主席樹套在一起就好了

?  外層的主席樹按照\(pre[x]\)來順序加點,樹內按照\(nxt\)的順序為關鍵字,然後對於每個節點(也就是區間啦),再開一棵主席樹,以\(nxt\)為根的順序,樹內以\(val[x]\)為關鍵字(也就是權值線段樹啦)

?  然後修改直接修改,查詢的時候我們先二分一下外層主席樹應該調用哪個\(rt\),也就是二分一個最大的\(pos\)滿足\(pre[pos]<l\),然後\(query(rt[pos],l,r)\)即可

  想清楚了的話還是比較好寫的

  有一些需要稍微註意一下的小細節

1、如果說對於那些後面已經沒有與其相同的數的位置,為了方便我們將其\(nxt\)賦成\(n+1\)

,所以這裏要註意主席樹的區間應該是\([1,n+1]\)

2、查詢的時候,要註意因為我們要求的是\(nxt[x]>r\),所以在查詢中涉及到的範圍應該是\(>\)而不是\(>=\)之類的,跟平時寫線段樹有那麽一點點小區別稍微註意一下

  

  代碼大概長這個樣子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010,M=200010,SEG=N*20;
struct Data{
    int pre,nxt,id,val;
    friend bool operator < (Data x,Data y)
    {return x.pre<y.pre;}
}a[N];
int loc[N];
int n,m,ans;
namespace NodeSeg{/*{{{*/
    int ch[SEG*20][2],mx[SEG*20],rt[SEG];
    int n,tot;
    int newnode(int pre){
        ch[++tot][0]=ch[pre][0],ch[tot][1]=ch[pre][1]; mx[tot]=mx[pre];
        return tot;
    }
    void pushup(int x){mx[x]=max(mx[ch[x][0]],mx[ch[x][1]]);}
    void _update(int pre,int &x,int lx,int rx,Data &delta){
        x=newnode(pre);
        if (lx==rx){mx[x]=delta.val;return;}
        int mid=lx+rx>>1;
        if (delta.id<=mid) _update(ch[pre][0],ch[x][0],lx,mid,delta);
        else _update(ch[pre][1],ch[x][1],mid+1,rx,delta);
        pushup(x);
    }
    void update(int pre,int x,Data delta){_update(rt[pre],rt[x],1,n,delta);}
    int _query(int x,int l,int r,int lx,int rx){
        if (mx[x]==0) return 0;
        if (l<=lx&&rx<=r) return mx[x];
        int mid=lx+rx>>1,ret=0;
        if (l<=mid) ret=max(ret,_query(ch[x][0],l,r,lx,mid));
        if (r>mid) ret=max(ret,_query(ch[x][1],l,r,mid+1,rx));
        return ret;
    }
    int query(int x,int l,int r){return _query(rt[x],l,r,1,n);}
}/*}}}*/
namespace NextSeg{/*{{{*/
    int ch[SEG][2],rt[SEG];
    int n,tot;
    int newnode(int pre,Data delta){
        ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1];
        NodeSeg::update(pre,tot,delta);
        return tot;
    }
    void _update(int pre,int &x,int lx,int rx,Data delta){
        x=newnode(pre,delta);
        if (lx==rx) return;
        int mid=lx+rx>>1;
        if (delta.nxt<=mid) _update(ch[pre][0],ch[x][0],lx,mid,delta);
        else _update(ch[pre][1],ch[x][1],mid+1,rx,delta);
    }
    void update(int x,Data delta){_update(rt[x-1],rt[x],1,n,delta);}
    int _query(int x,int l,int r,int lx,int rx){
        if (r<lx&&rx<=n) return NodeSeg::query(x,l,r);
        int mid=lx+rx>>1,ret=0;
        if (r<mid) ret=max(ret,_query(ch[x][0],l,r,lx,mid));
        ret=max(ret,_query(ch[x][1],l,r,mid+1,rx));
        return ret;
    }
    int query(int x,int l,int r){return _query(rt[x],l,r,1,n);}
}/*}}}*/
int read(){
    int ret=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while ('0'<=ch&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret;
}

void prework(){
    for (int i=1;i<=n;++i) a[i].pre=0,a[i].nxt=n+1;
    for (int i=1;i<=n;++i){
        a[i].id=i;
        if (loc[a[i].val]) 
            a[loc[a[i].val]].nxt=i,a[i].pre=loc[a[i].val];
        loc[a[i].val]=i;
    }
    NodeSeg::n=n+1; NextSeg::n=n+1;
}

int get_pos(int x){
    int l=1,r=n,mid,ret=l;
    while (l<=r){
        mid=l+r>>1;
        if (x<=a[mid].pre) r=mid-1;
        else l=mid+1;
    }
    return l-1;
}

int main(){/*{{{*/
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    int x,y,x1,y1,pos;
    n=read(); m=read();
    for (int i=1;i<=n;++i) a[i].val=read();
    prework();
    sort(a+1,a+1+n);
    for (int i=1;i<=n;++i)
        NextSeg::update(i,a[i]);
    for (int i=1;i<=m;++i){
        x1=read(); y1=read();
        x=min((x1+ans)%n+1,(y1+ans)%n+1);
        y=max((x1+ans)%n+1,(y1+ans)%n+1);
        pos=get_pos(x);
        ans=NextSeg::query(pos,x,y);
        printf("%d\n",ans);
    }
}/*}}}*/

【bzoj3489】A simple rmq problem