由运算符有优先级可以想到先算优先级小的,然后两边递归,但符号比较少,有大量相同的,同级之间怎么办呢?因为运算符满足结合律,同级之间选一个然后两边递归也是没问题的,然后我们想到用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]];
}

 

posted on 2018-01-22 18:54  湮灭之瞳  阅读(530)  评论(0编辑  收藏  举报