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;
    }
    
  • 相关阅读:
    Android高手进阶教程(十八)之---列出Android设备中所有启动的服务,及判断某个服务是否开启!
    Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!
    Android 中的拿来主义(编译,反编译,AXMLPrinter2,smali,baksmali)!
    Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
    JavaWeb的三大组件之过滤器
    JavaWeb的三大组件之事件监听组件(Listener)
    CommonUtils工具类
    Java代码生成不重复的32位长的大写字符串
    JNDI和Local
    Web项目里的各种路径
  • 原文地址:https://www.cnblogs.com/AKMer/p/10000285.html
Copyright © 2011-2022 走看看