bzoj 3489 A simple rmq problem——主席树套线段树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489

题解:http://www.itdaan.com/blog/2017/11/24/9bc46b690756fe252e17fc3ca90aa01.html

所以就没写KD-tree、树套堆、分块,而是写了树套树。

限制条件是:pr<L;nt>R;L<= i <=R。

对pr排序后建主席树,调用1~L-1的主席树就能限制好第一个条件;主席树里维护 nt 的值域,调用R+1~n+1的部分就能限制好第二个条件;因为有第三个条件,所以每个点上带一个线段树,维护 i 的位置,记录max值,就行了。

调了半天原来是读入理解错了;1A好高兴。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5,M=N*20,M2=M*20;
int n,m,tot,tt2,pre[N],rt[N],ans;
struct Node{
    int pr,i,nt,c;
}a[N];
struct Tr{
    int ls,rs,rt;
}tr[M];
struct T{
    int ls,rs,mx;
}t[M2];
int rdn()
{
    int ret=0;bool fx=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return fx?ret:-ret;
}
bool cmpl(Node u,Node v){return u.pr<v.pr;}
void insert(int &cr,int pre,int l,int r,Node k)
{
    cr=++tt2; t[cr].ls=t[pre].ls; t[cr].rs=t[pre].rs;
    t[cr].mx=max(t[pre].mx,k.c);

//    printf(" bdin: l=%d r=%d mx=%d
",l,r,t[cr].mx);

    if(l==r) return;
    int mid=l+r>>1;
    if(k.i<=mid) insert(t[cr].ls,t[pre].ls,l,mid,k);
    else insert(t[cr].rs,t[pre].rs,mid+1,r,k);
}
void build(int &cr,int pre,int l,int r,Node k)
{
    cr=++tot; tr[cr].ls=tr[pre].ls; tr[cr].rs=tr[pre].rs;
    insert(tr[cr].rt,tr[pre].rt,1,n,k);
//    printf("bdout: l=%d r=%d rt=%d
",l,r,tr[cr].rt);

    if(l==r) return; int mid=l+r>>1;
    if(k.nt<=mid) build(tr[cr].ls,tr[pre].ls,l,mid,k);
    else build(tr[cr].rs,tr[pre].rs,mid+1,r,k);
}
int find(int x)
{
    int l=1,r=n,ret=0;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(a[mid].pr<=x)ret=mid,l=mid+1;
        else r=mid-1;
    }
    return ret;
}
int query(int cr,int l,int r,int L,int R)
{
    if(!cr) return 0;
//    printf(" qin: l=%d r=%d(L=%d R=%d)
",l,r,L,R);
    if(l>=L&&r<=R) return t[cr].mx;
    int mid=l+r>>1,ret=0;
    if(L<=mid) ret=query(t[cr].ls,l,mid,L,R);
    if(mid<R) ret=max(ret,query(t[cr].rs,mid+1,r,L,R));
//    printf(" qin: l=%d r=%d ret=%d
",l,r,ret);
    return ret;
}
int query(int cr,int l,int r,int L,int R,int ql,int qr)
{
    if(!cr)return 0;
//    printf("qout: l=%d r=%d rt=%d(L=%d R=%d)
",
//           l,r,tr[cr].rt,L,R);
    if(l>=L&&r<=R) return query(tr[cr].rt,1,n,ql,qr);
    int mid=l+r>>1,ret=0;
    if(L<=mid) ret=query(tr[cr].ls,l,mid,L,R,ql,qr);
    if(mid<R) ret=max(ret,query(tr[cr].rs,mid+1,r,L,R,ql,qr));
//    printf("qout: l=%d r=%d ret=%d
",l,r,ret);
    return ret;
}
int main()
{
    n=rdn(); m=rdn();
    for(int i=1,d;i<=n;i++)
    {
        d=rdn(); a[i].pr=pre[d];
        a[i].i=i; a[i].c=d; pre[d]=i;
    }
    for(int i=1;i<=n;i++) pre[i]=n+1;
    for(int i=n;i;i--)
        a[i].nt=pre[a[i].c],pre[a[i].c]=i;

    sort(a+1,a+n+1,cmpl);
    for(int i=1;i<=n;i++)
        build(rt[i],rt[i-1],1,n+1,a[i]);

    for(int i=1,l,r,x,y,k;i<=m;i++)
    {
        x=rdn(); y=rdn();
        l=min((x+ans)%n+1,(y+ans)%n+1);
        r=max((x+ans)%n+1,(y+ans)%n+1);
        k=find(l-1);

//        printf("st: l=%d r=%d k=%d
",l,r,k);
        
        ans=query(rt[k],1,n+1,r+1,n+1,l,r);
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9719242.html