• 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;
    }
  • 相关阅读:
    【HAOI2014】走出金字塔
    【HAOI2008】圆上的整点
    LOJ #116 有源汇点有上下界的最大流
    ZOJ [P2314] 无源汇点有上下界模版
    最小费用最大流模版
    最大流模版 dinic
    最大流模版 EK
    HDU [P1533]
    HDU [2255] 奔小康赚大钱
    POJ [P2289] Jamie's Contact Groups
  • 原文地址:https://www.cnblogs.com/Narh/p/9719242.html
Copyright © 2020-2023  润新知