zoukankan      html  css  js  c++  java
  • [bzoj3489]A simple rmq problem

    传送门

    这个题我实在不知道怎么办了,到现在依然没能在bzojAC,本机测试速度还可以,复杂度似乎也没问题,希望有大佬能指出一下错误!

    问题已解决,加个剪枝就好了(果然kd-tree还是离不开剪枝啊)!

    我的思路大概是对于每个数记录它的上一次出现的位置(pre_i),当前位置(i),下次出现位置(nxt_i)
    按照(pre)排序,对于(i)(nxt)建立k-d tree,由于涉及到单点修改,所以记录一下从根到每个点的路径,这样能保证在(log_n)的时间内完成修改。
    按理说复杂度应该是过得去的,可能是本人的常数实在写得大!!
    TLE代码(可持久化k-d tree):

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    void read(int &x) {
        char ch; bool ok;
        for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
        for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define rg register
    #define pushup(x) s[x].sum=max(max(s[s[x].l].sum,s[s[x].r].sum),s[x].v)
    const int maxn=1e5+1;
    struct oo{int d[2],mn[2],mx[2],l,r,sum,v;}s[maxn*20];
    struct o{int d[3],id,x;}f[maxn];
    int n,m,rt[maxn],w[maxn],g,id,ans,d[maxn],c[maxn];
    bool cmp(oo a,oo b){return a.d[g]<b.d[g];}
    bool cmp1(o a,o b){return a.d[2]<b.d[2];}
    inline void update(int x)
    {
        if(s[x].l)
        {
            s[x].mn[0]=min(s[s[x].l].mn[0],s[x].mn[0]);
            s[x].mn[1]=min(s[s[x].l].mn[1],s[x].mn[1]);
            s[x].mx[0]=max(s[s[x].l].mx[0],s[x].mx[0]);
            s[x].mx[1]=max(s[s[x].l].mx[1],s[x].mx[1]);
        }
        if(s[x].r)
        {
            s[x].mn[0]=min(s[s[x].r].mn[0],s[x].mn[0]);
            s[x].mn[1]=min(s[s[x].r].mn[1],s[x].mn[1]);
            s[x].mx[0]=max(s[s[x].r].mx[0],s[x].mx[0]);
            s[x].mx[1]=max(s[s[x].r].mx[1],s[x].mx[1]);
        }
    }
    inline void build(int l,int r,int fa,int d,int v,int dep)
    {
        int mid=(l+r)>>1;g=d;
        nth_element(s+l,s+mid,s+r+1,cmp);
        s[mid].mn[0]=s[mid].mx[0]=s[mid].d[0];if(!v)s[fa].l=mid;else s[fa].r=mid;
        s[mid].mn[1]=s[mid].mx[1]=s[mid].d[1];c[s[mid].d[0]]=c[s[fa].d[0]]|(v<<dep);
        if(l!=mid)build(l,mid-1,mid,!d,0,dep+1);
        if(r!=mid)build(mid+1,r,mid,!d,1,dep+1);
        update(mid);return ;
    }
    inline void change(int x,int &k,int l,int r,int val,int dep)
    {
        k=++id,s[k]=s[x];
        if(l==s[k].d[0]){s[k].v=val,s[k].sum=max(s[k].sum,val);return ;}
        change((c[l]&(1<<(dep+1)))?s[x].r:s[x].l,(c[l]&(1<<(dep+1)))?s[k].r:s[k].l,l,r,val,dep+1);
        pushup(k);
    }
    inline void get(int x,int l,int r,int ll,int rr)
    {
        if(l<=s[x].mn[0]&&r>=s[x].mx[0]&&ll<=s[x].mn[1]&&rr>=s[x].mx[1]){ans=max(ans,s[x].sum);return ;}
        else if(l<=s[x].d[0]&&r>=s[x].d[0]&&ll<=s[x].d[1]&&rr>=s[x].d[1])ans=max(ans,s[x].v);
        if(s[x].l&&l<=s[s[x].l].mx[0]&&ll<=s[s[x].l].mx[1])get(s[x].l,l,r,ll,rr);
        if(s[x].r&&r>=s[s[x].r].mn[0]&&rr>=s[s[x].r].mn[1])get(s[x].r,l,r,ll,rr);
    }
    int main()
    {
        read(n),read(m);
        for(rg int i=1;i<=n;i++)s[i].d[1]=f[i].d[1]=n+1;
        for(rg int i=1,x;i<=n;i++)read(x),f[i].d[2]=w[x],f[i].id=i,f[i].d[0]=s[i].d[0]=i,f[w[x]].d[1]=s[w[x]].d[1]=i,w[x]=i,f[i].x=x;
        rt[0]=(1+n)>>1;build(1,n,0,0,0,1);sort(f+1,f+n+1,cmp1);int now=1;id=n;
        while(f[now].d[2]==0&&now<=n)change(rt[0],rt[0],f[now].d[0],f[now].d[1],f[now].x,1),now++;
        for(rg int i=1;i<=n;i++)
        {
            rt[i]=rt[i-1];
            while(f[now].d[2]==i&&now<=n)change(rt[i],rt[i],f[now].d[0],f[now].d[1],f[now].x,1),now++;
        }
        for(rg int i=1,x,y,l,r;i<=m;i++)
        {
            read(x),read(y),l=min((x+ans)%n+1,(y+ans)%n+1),r=max((x+ans)%n+1,(y+ans)%n+1);
            ans=0,get(rt[l-1],l,r,r+1,n+1),printf("%d
    ",ans);
        }
    }
    

    这个有意思呢,加个最优性剪枝就快了好几倍
    AC代码:

    #pragma GCC optimize(3)
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    void read(int &x) {
        char ch; bool ok;
        for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
        for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define rg register
    #define pushup(x) s[x].sum=max(max(s[s[x].l].sum,s[s[x].r].sum),s[x].v)
    const int maxn=1e5+1;
    struct oo{int d[2],mn[2],mx[2],l,r,sum,v;}s[maxn*20];
    struct o{int d[3],id,x;}f[maxn];
    int n,m,rt[maxn],w[maxn],g,id,ans,d[maxn],c[maxn];
    bool cmp(oo a,oo b){return a.d[g]<b.d[g];}
    bool cmp1(o a,o b){return a.d[2]<b.d[2];}
    inline void update(int x)
    {
        if(s[x].l)
        {
            s[x].mn[0]=min(s[s[x].l].mn[0],s[x].mn[0]);
            s[x].mn[1]=min(s[s[x].l].mn[1],s[x].mn[1]);
            s[x].mx[0]=max(s[s[x].l].mx[0],s[x].mx[0]);
            s[x].mx[1]=max(s[s[x].l].mx[1],s[x].mx[1]);
        }
        if(s[x].r)
        {
            s[x].mn[0]=min(s[s[x].r].mn[0],s[x].mn[0]);
            s[x].mn[1]=min(s[s[x].r].mn[1],s[x].mn[1]);
            s[x].mx[0]=max(s[s[x].r].mx[0],s[x].mx[0]);
            s[x].mx[1]=max(s[s[x].r].mx[1],s[x].mx[1]);
        }
    }
    inline void build(int l,int r,int fa,int d,int v,int dep)
    {
        int mid=(l+r)>>1;g=d;
        nth_element(s+l,s+mid,s+r+1,cmp);
        s[mid].mn[0]=s[mid].mx[0]=s[mid].d[0];if(!v)s[fa].l=mid;else s[fa].r=mid;
        s[mid].mn[1]=s[mid].mx[1]=s[mid].d[1];c[s[mid].d[0]]=c[s[fa].d[0]]|(v<<dep);
        if(l!=mid)build(l,mid-1,mid,!d,0,dep+1);
        if(r!=mid)build(mid+1,r,mid,!d,1,dep+1);
        update(mid);return ;
    }
    inline void change(int x,int &k,int l,int r,int val,int dep)
    {
        k=++id,s[k]=s[x];
        if(l==s[k].d[0]){s[k].v=val,s[k].sum=max(s[k].sum,val);return ;}
        change((c[l]&(1<<(dep+1)))?s[x].r:s[x].l,(c[l]&(1<<(dep+1)))?s[k].r:s[k].l,l,r,val,dep+1);
        pushup(k);
    }
    inline void get(int x,int l,int r,int ll,int rr)
    {
    	if(l>s[x].mx[0]||r<s[x].mn[0]||ll>s[x].mx[1]||rr<s[x].mn[1]||ans>s[x].sum)return ;
        if(l<=s[x].mn[0]&&r>=s[x].mx[0]&&ll<=s[x].mn[1]&&rr>=s[x].mx[1]){ans=max(ans,s[x].sum);return ;}
        else if(l<=s[x].d[0]&&r>=s[x].d[0]&&ll<=s[x].d[1]&&rr>=s[x].d[1])ans=max(ans,s[x].v);
        if(s[x].l&&l<=s[s[x].l].mx[0]&&ll<=s[s[x].l].mx[1])get(s[x].l,l,r,ll,rr);
        if(s[x].r&&r>=s[s[x].r].mn[0]&&rr>=s[s[x].r].mn[1])get(s[x].r,l,r,ll,rr);
    }
    int main()
    {
    //  freopen("1.in","r",stdin);
    //  freopen("my.out","w",stdout);
        read(n),read(m);
        for(rg int i=1;i<=n;i++)s[i].d[1]=f[i].d[1]=n+1;
        for(rg int i=1,x;i<=n;i++)read(x),f[i].d[2]=w[x],f[i].id=i,f[i].d[0]=s[i].d[0]=i,f[w[x]].d[1]=s[w[x]].d[1]=i,w[x]=i,f[i].x=x;
        rt[0]=(1+n)>>1;build(1,n,0,0,0,1);sort(f+1,f+n+1,cmp1);int now=1;id=n;
        while(f[now].d[2]==0&&now<=n)change(rt[0],rt[0],f[now].d[0],f[now].d[1],f[now].x,1),now++;
        for(rg int i=1;i<=n;i++)
        {
            rt[i]=rt[i-1];
            while(f[now].d[2]==i&&now<=n)change(rt[i],rt[i],f[now].d[0],f[now].d[1],f[now].x,1),now++;
        }
        for(rg int i=1,x,y,l,r;i<=m;i++)
        {
            read(x),read(y),l=min((x+ans)%n+1,(y+ans)%n+1),r=max((x+ans)%n+1,(y+ans)%n+1);
            ans=0,get(rt[l-1],l,r,r+1,n+1),printf("%d
    ",ans);
        }
    }
    
  • 相关阅读:
    基于React 的audio音频播放组件
    React Context 的基本用法
    Video-React 视频播放组件的使用
    Html5 Canvas 使用
    React 中使用富文本编辑器 Braft Editor ,并集成上传图片功能
    ant design pro 项目实现路由级的动态加载按需加载
    确保代码仓库中包含 yarn.lock 文件
    ES6 对象解构赋值(浅拷贝 VS 深拷贝)
    JS 中判断数据类型是否为 null、undefined 或 NaN
    js中的数据类型及判断方法
  • 原文地址:https://www.cnblogs.com/lcxer/p/10279061.html
Copyright © 2011-2022 走看看