zoukankan      html  css  js  c++  java
  • wc2016鏖战表达式(可持久treap)

    由运算符有优先级可以想到先算优先级小的,然后两边递归,但符号比较少,有大量相同的,同级之间怎么办呢?因为运算符满足结合律,同级之间选一个然后两边递归也是没问题的,然后我们想到用fhqtreap进行维护,但堆那一维不是随机的,所以我们merge时再按两棵树的大小比例搞一个随机,把小的往大的上合(玄学,如果直接把小的和到大的上得30分),另外说一下是满足交换律才能用这种方法的,要不满足交换律转一下值就全换了,还要遍历整棵树来维护。

    注意merge(l,r)应保证r里的元素的二叉排序树那一维的劝值大于l。

    第一次写这种数据结构,直接抄的题解

    PS:代码来源:http://blog.csdn.net/werkeytom_ftd/article/details/50635596;

    #include "expr.h"
    #include<ctime>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=30000000+10;
    int root[maxn],siz[maxn],tr[maxn][2],fix[maxn];
    bool bz[maxn];
    Data key[maxn],num[maxn],wdc;
    int i,j,k,l,mid,r,n,m,tot,top;
    int newno(int x){
        siz[++tot]=siz[x];tr[tot][0]=tr[x][0];tr[tot][1]=tr[x][1];
        fix[tot]=fix[x];bz[tot]=bz[x];key[tot]=key[x];num[tot]=num[x];
        return tot;
    }
    void update(int x){
        siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+1;
        if(fix[x]<=100&&tr[x][0]&&tr[x][1])
        num[x]=F(num[tr[x][0]],num[tr[x][1]],fix[x]);
        else num[x]=key[x];
    }
    void mark(int &x){
        if(!x)return;
        int y=newno(x);
        bz[y]^=1;swap(tr[y][0],tr[y][1]);
        x=y;
    }
    void pushdown(int x){
        if(bz[x]){mark(tr[x][0]);mark(tr[x][1]);bz[x]=0;}
    }
    bool cmp(int x,int y){
        if(fix[x]==fix[y])return ((siz[y])<siz[x]);
        else return fix[x]<fix[y];
    }
    void merge(int l,int r,int &x){
        if(!l||!r){x=l+r;return;}
        pushdown(l);pushdown(r);
        int t;
        if(cmp(l,r)){
            t=newno(l);
            merge(tr[l][1],r,tr[t][1]);
        }
        else{
            t=newno(r);
            merge(l,tr[r][0],tr[t][0]);
        }
        update(t);
        x=t;
    }
    void split(int x,int y,int &l,int &r){
        if(!x){l=r=0;return;}
        if(!y){l=0;r=x;return;}
        pushdown(x);
        int t;
        if(siz[tr[x][0]]>=y){
            split(tr[x][0],y,l,r);
            t=newno(x);tr[t][0]=r;
            update(t);r=t;
        }
        else{
            split(tr[x][1],y-siz[tr[x][0]]-1,l,r);
            t=newno(x);tr[t][1]=l;
            update(t);l=t;
        }
    }
    void init(int test_id,int n,int m,int k,const Data *a,const int *ops){
        srand(time(0));
        wdc=a[0];top=0;int t;
        for(int i=n;i>=1;--i){
            t=newno(0);siz[t]=1;fix[t]=101;
            key[t]=num[t]=a[i-1];
            merge(t,root[0],root[0]);
            if(i>1){
                int t=newno(0);
                siz[t]=1;fix[t]=ops[i-1];key[t]=num[t]=wdc;
                merge(t,root[0],root[0]);
            }
        }
    }
    Data modify_data(int id,int pos,Data x){
        ++top;++pos;
        split(root[id],2*pos-1,l,r);
        split(l,2*pos-2,l,mid);
        int t=newno(mid);
        key[t]=num[t]=x;
        merge(l,t,l);merge(l,r,root[top]);
        return num[root[top]];
    }
    Data modify_op(int id,int pos,int new_op){
        ++top;
        split(root[id],2*pos,l,r);
        split(l,2*pos-1,l,mid);
        int t=newno(mid);
        fix[t]=new_op;
        merge(l,t,l);merge(l,r,root[top]);
        return num[root[top]];
    }
    Data reverse(int id,int l,int r){
        ++top;
        ++l,++r;j=l;k=r;
        split(root[id],2*k-1,l,r);
        split(l,2*j-2,l,mid);
        mark(mid);
        merge(l,mid,l);
        merge(l,r,root[top]);
        return num[root[top]];
    }
  • 相关阅读:
    简单C#、asp.net mvc验证码的实现
    c# 局域网文件传输实例
    c# http get请求与post请求实例
    轻松3步实现c#windowsform窗体美化
    c#内部类的使用
    java
    java
    java
    java
    java
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8330609.html
Copyright © 2011-2022 走看看