鏖(áo)战
第一次做这种实现接口的交互题!感觉还挺好玩的
朴素的思想就是先找到当前最低优先级的运算符,把式子分成几部分递归计算,因为有交换律和结合律所以同优先级乱算就可以了
优先级这个东西好像在treap里也有?
所以我们可以用fhqtreap维护整个式子,运算符的优先级原封不动,因为数值一定要是叶子节点所以数值的优先级为$+\infty$
为了保证treap不会退化,在merge($x$,$y$)时如果$fix_x=fix_y$那么就按(以$x$为根的概率和以$y$为根的概率之比为$\dfrac{siz_x}{siz_y}$)来合并
需要可持久化,pushdown时要复制两个节点,修改时也要复制节点
因为有维护标记,所以merge时以哪个点为根就复制再pushdown哪个点,split时先复制然后pushdown,两种操作都要在最后pushup
运行的时候新建一个文件,在这个文件上编译调试即可
#include"expr.cpp" #include"grader.cpp"
我是不是太智障了...自己写swap没加引用符号调了一晚上调不出来
第一次交90,后面两个点调用F的次数超限,去看了一下栋爷的博客,发现初始化时反着merge就可以A,不知道是什么原理w求解释
#include<stdio.h> #include<stdlib.h> #include"expr.h" #define maxn 30000010 int rt[20010],l[maxn],r[maxn],rv[maxn],siz[maxn],fix[maxn],tot,M; Data s[maxn]; bool cmp(int x,int y){ if(fix[x]==fix[y])return rand()%(siz[x]+siz[y])<siz[x]; return fix[x]<fix[y]; } void pushup(int x){ siz[x]=siz[l[x]]+siz[r[x]]+1; if(fix[x]<101&&l[x]!=0&&r[x]!=0)s[x]=F(s[l[x]],s[r[x]],fix[x]); } int node(int u){ tot++; int&x=tot; l[x]=l[u]; r[x]=r[u]; siz[x]=siz[u]; rv[x]=rv[u]; fix[x]=fix[u]; s[x]=s[u]; return x; } void swap(int&a,int&b){a^=b^=a^=b;} void gao(int&u){ int x=node(u); rv[x]^=1; swap(l[x],r[x]); u=x; } void pushdown(int x){ if(rv[x]){ if(l[x])gao(l[x]); if(r[x])gao(r[x]); rv[x]=0; } } struct pair{ int l,r; pair(int a=0,int b=0){l=a;r=b;} }; pair split(int x,int k){ if(x==0)return pair(); int u=node(x); pushdown(u); pair s; if(k<=siz[l[u]]){ s=split(l[u],k); l[u]=s.r; s.r=u; }else{ s=split(r[u],k-siz[l[u]]-1); r[u]=s.l; s.l=u; } pushup(u); return s; } int merge(int x,int y){ if(x==0&&y==0)return 0; if(x==0)return node(y); if(y==0)return node(x); int u; if(cmp(x,y)){ u=node(x); pushdown(u); r[u]=merge(r[u],y); }else{ u=node(y); pushdown(u); l[u]=merge(x,l[u]); } pushup(u); return u; } void init(int test_id,int n,int m,int k,const Data*a,const int*ops){ srand(19260817); int i; rt[0]=1; siz[1]=1; fix[1]=101; s[1]=a[n-1]; tot=1; for(i=n-1;i>0;i--){ tot++; siz[tot]=2; fix[tot]=ops[i]; tot++; siz[tot]=1; fix[tot]=101; s[tot]=a[i-1]; l[tot-1]=tot; rt[0]=merge(tot-1,rt[0]); } } Data modify_data(int id,int pos,Data x){ pair a,b; int u; a=split(rt[id],pos<<1); b=split(a.r,1); u=node(b.l); s[u]=x; M++; rt[M]=merge(a.l,merge(u,b.r)); return s[rt[M]]; } Data modify_op(int id,int pos,int new_op){ pair a,b; int u; a=split(rt[id],(pos<<1)-1); b=split(a.r,1); u=node(b.l); fix[u]=new_op; M++; rt[M]=merge(a.l,merge(u,b.r)); return s[rt[M]]; } Data reverse(int id,int l,int r){ pair a,b; a=split(rt[id],l<<1); b=split(a.r,(r-l)<<1|1); gao(b.l); M++; rt[M]=merge(a.l,merge(b.l,b.r)); return s[rt[M]]; }