zoukankan      html  css  js  c++  java
  • POJ3580:SuperMemo

    浅谈(splay)https://www.cnblogs.com/AKMer/p/9979592.html

    浅谈(fhq)_(treap)https://www.cnblogs.com/AKMer/p/9981274.html

    题目传送门:http://poj.org/problem?id=3580

    对于(REVOLVE)操作,就相当于把([r-t+1,r])剪切下来粘贴到([l-1,l])中间,其余的操作都是平衡树较为模板的操作了。记得把零号点的最小值赋成(inf),要不然空儿子更新父亲信息就会出错。下传标记记得不要传给空儿子,否则会加爆。

    时间复杂度:(O((n+m)logn))

    空间复杂度:(O(n))

    (splay)代码如下:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    const int maxn=2e5+5,inf=2e9;
     
    int n,m;
    char s[10];
    int a[maxn];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    struct Splay {
        int tot,root;
        bool rev[maxn];
        int add[maxn],val[maxn],mn[maxn];
        int siz[maxn],fa[maxn],son[maxn][2];
     
        int newnode(int v) {
            siz[++tot]=1;
            val[tot]=mn[tot]=v;
            return tot;
        }
     
        void update(int p) {
            siz[p]=siz[son[p][0]]+1+siz[son[p][1]];
            mn[p]=min(min(mn[son[p][0]],mn[son[p][1]]),val[p]);
        }
     
        void build(int l,int r,int lst) {
            if(r<l)return;
            if(l==r) {
                siz[l]=1,val[l]=mn[l]=a[l];
                fa[l]=lst,son[lst][l>lst]=l;
                return;
            }
            int mid=(l+r)>>1;
            val[mid]=a[mid];
            fa[mid]=lst,son[lst][mid>lst]=mid;
            build(l,mid-1,mid),build(mid+1,r,mid);
            update(mid);
        }
         
        void prepare() {
            mn[0]=inf,tot=n+2,build(1,n+2,0),root=(n+3)>>1;
        }
     
        void make_rev_tag(int p) {
            if(!p)return;
            rev[p]^=1,swap(son[p][0],son[p][1]);
        }
     
        void make_add_tag(int p,int v) {
            if(!p)return;
            val[p]+=v,add[p]+=v,mn[p]+=v;
        }
     
        void push_down(int p) {
            if(rev[p]) {
                make_rev_tag(son[p][0]);
                make_rev_tag(son[p][1]);
                rev[p]=0;
            }
            if(add[p]) {
                make_add_tag(son[p][0],add[p]);
                make_add_tag(son[p][1],add[p]);
                add[p]=0;
            }
        }
     
        int find(int u,int rk) {
            push_down(u);
            if(siz[son[u][0]]+1==rk)return u;
            if(siz[son[u][0]]>=rk)return find(son[u][0],rk);
            return find(son[u][1],rk-siz[son[u][0]]-1);
        }
     
        int t(int u) {
            return son[fa[u]][1]==u;
        }
     
        void rotate(int u) {
            int ret=t(u),f=fa[u],s=son[u][ret^1];
            son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
            fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
            fa[f]=u;update(f),update(u);
        }
     
        void splay(int goal,int u) {
            int tmp=fa[goal];
            while(fa[u]!=tmp) {
                if(fa[fa[u]]!=tmp) {
                    if(t(fa[u])==t(u))rotate(fa[u]);
                    else rotate(u);
                }
                rotate(u);
            }
            if(!tmp)root=u;
        }
     
        void ADD(int l,int r,int v) {
            int u1=find(root,l-1),u2=find(root,r+1);
            splay(root,u1),splay(son[u1][1],u2);
            make_add_tag(son[u2][0],v);
            update(u2),update(u1);
        }
     
        void REVERSE(int l,int r) {
            int u1=find(root,l-1),u2=find(root,r+1);
            splay(root,u1),splay(son[u1][1],u2);
            make_rev_tag(son[u2][0]);
        }
     
        int cut(int l,int r) {
            int u1=find(root,l-1),u2=find(root,r+1);
            splay(root,u1),splay(son[u1][1],u2);
            int tmp=son[u2][0];
            son[u2][0]=fa[tmp]=0;
            update(u2),update(u1);
            return tmp;
        }
     
        void paste(int pos,int node) {
            int u1=find(root,pos-1),u2=find(root,pos);
            splay(root,u1),splay(son[u1][1],u2);
            fa[node]=u2,son[u2][0]=node;
            update(u2),update(u1);
        }
     
        int query(int l,int r) {
            int u1=find(root,l-1),u2=find(root,r+1);
            splay(root,u1),splay(son[u1][1],u2);
            return mn[son[u2][0]];
        }
    }T;
     
    int main() {
        n=read();
        for(int i=2;i<=n+1;i++)
            a[i]=read();
        a[1]=a[n+2]=inf;
        T.prepare();m=read();
        for(int i=1;i<=m;i++) {
            scanf("%s",s+1);
            if(s[1]=='A') {
                int l=read()+1,r=read()+1,v=read();
                T.ADD(l,r,v);
            }
            if(s[1]=='R') {
                int l=read()+1,r=read()+1;
                if(s[4]=='E')T.REVERSE(l,r);
                else {
                    int t=read()%(r-l+1);
                    int tmp=T.cut(r-t+1,r);
                    T.paste(l,tmp);
                }
            }
            if(s[1]=='I') {
                int pos=read()+1,v=read();
                T.paste(pos+1,T.newnode(v));
            }
            if(s[1]=='D') {
                int pos=read()+1;
                T.cut(pos,pos);
            }
            if(s[1]=='M') {
                int l=read()+1,r=read()+1;
                printf("%d
    ",T.query(l,r));
            }
        }
        return 0;
    }
    

    (fhq)_(treap)版代码如下:

    #include <ctime>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef pair<int,int> pii;
     
    const int maxn=2e5+5,inf=2e9;
     
    int n,m;
    char s[10];
    int a[maxn];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    struct fhq_treap {
        int tot,root;
        bool rev[maxn];
        int val[maxn],mn[maxn],add[maxn];
        int siz[maxn],fix[maxn],son[maxn][2];
     
        int newnode(int v) {
            siz[++tot]=1;
            fix[tot]=rand();
            val[tot]=mn[tot]=v;
            return tot;
        }
     
        void update(int p) {
            siz[p]=siz[son[p][0]]+1+siz[son[p][1]];
            mn[p]=min(min(mn[son[p][0]],mn[son[p][1]]),val[p]);
        }
         
        void build(int l,int r,int lst) {
            if(r<l)return;
            if(l==r) {
                siz[l]=1,fix[l]=rand();
                son[lst][l>lst]=l;
                val[l]=mn[l]=a[l];
                return;
            }
            int mid=(l+r)>>1;
            val[mid]=a[mid],fix[mid]=rand();
            son[lst][mid>lst]=mid;
            build(l,mid-1,mid),build(mid+1,r,mid);
            update(mid);
        }
     
        void prepare() {
            mn[0]=inf,tot=n,build(1,n,0),root=(n+1)>>1;
        }
     
        void make_add_tag(int u,int v) {
            if(!u)return;
            val[u]+=v,add[u]+=v,mn[u]+=v;
        }
     
        void make_rev_tag(int u) {
            if(!u)return;
            rev[u]^=1,swap(son[u][0],son[u][1]);
        }
     
        void push_down(int u) {
            if(add[u]) {
                make_add_tag(son[u][0],add[u]);
                make_add_tag(son[u][1],add[u]);
                add[u]=0;
            }
            if(rev[u]) {
                make_rev_tag(son[u][0]);
                make_rev_tag(son[u][1]);
                rev[u]=0;
            }
        }
     
        pii split(int u,int rk) {
            if(!rk)return make_pair(0,u);
            if(rk==siz[u])return make_pair(u,0);
            push_down(u);
            if(siz[son[u][0]]>=rk) {
                pii tmp=split(son[u][0],rk);
                son[u][0]=tmp.second,update(u);
                return make_pair(tmp.first,u);
            }
            else {
                pii tmp=split(son[u][1],rk-siz[son[u][0]]-1);
                son[u][1]=tmp.first,update(u);
                return make_pair(u,tmp.second);
            }
        }
     
        int merge(int a,int b) {
            if(!a||!b)return a+b;
            push_down(a),push_down(b);
            if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
            else return son[b][0]=merge(a,son[b][0]),update(b),b;
        }
     
        void ADD(int l,int r,int v) {
            pii tmp1=split(root,r);
            pii tmp2=split(tmp1.first,l-1);
            make_add_tag(tmp2.second,v);
            root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
        }
     
        void REVERSE(int l,int r) {
            pii tmp1=split(root,r);
            pii tmp2=split(tmp1.first,l-1);
            make_rev_tag(tmp2.second);
            root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
        }
     
     
        int cut(int l,int r) {
            pii tmp1=split(root,r);
            pii tmp2=split(tmp1.first,l-1);
            root=merge(tmp2.first,tmp1.second);
            return tmp2.second;
        }
     
        void paste(int pos,int node) {
            pii tmp=split(root,pos-1);
            root=merge(merge(tmp.first,node),tmp.second);
        }
     
        int query(int l,int r) {
            pii tmp1=split(root,r);
            pii tmp2=split(tmp1.first,l-1);
            int res=mn[tmp2.second];
            root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
            return res;
        }
    }T;
     
    int main() {
        srand(time(0)),n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        T.prepare();m=read();
        for(int i=1;i<=m;i++) {
            scanf("%s",s+1);
            if(s[1]=='A') {
                int l=read(),r=read(),v=read();
                T.ADD(l,r,v);
            }
            if(s[1]=='R') {
                int l=read(),r=read();
                if(s[4]=='E')T.REVERSE(l,r);
                else {
                    int t=read()%(r-l+1);
                    int tmp=T.cut(r-t+1,r);
                    T.paste(l,tmp);
                }
            }
            if(s[1]=='I') {
                int pos=read(),v=read();
                T.paste(pos+1,T.newnode(v));
            }
            if(s[1]=='D') {
                int pos=read();
                T.cut(pos,pos);
            }
            if(s[1]=='M') {
                int l=read(),r=read();
                printf("%d
    ",T.query(l,r));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java实现 LeetCode 50 Pow(x,n)
    Java实现 LeetCode 50 Pow(x,n)
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 49 字母异位词分组
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 48 旋转图像
    Java实现 LeetCode 47 全排列 II(二)
    Java实现 LeetCode 47 全排列 II(二)
  • 原文地址:https://www.cnblogs.com/AKMer/p/10000285.html
Copyright © 2011-2022 走看看