[Splay][线段树] jzoj P5662 尺树寸泓
题解
- 每次子树和只有 2 个点会修改
- 旋转会导致统计子树的答案会比较麻烦
- 而这是一棵平衡树,中序遍历在平衡树中的相对位置不会变
- 而在中序遍历中,一个点的子树也是一个区间
- 所以,我们可以把中序遍历搞出来,维护每个子树相对应的区间
- 用线段树维护就可以了
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define mo 1000000007 6 using namespace std; 7 struct data{ int l,r; }son[2000010]; 8 struct splay{ int l,r;long long mul; }tree[2000010*4]; 9 long long f[2000010],sum[2000010],a[2000010],fa[2000010],size[2000010],num[2000010],numl[2000010],ans; 10 int n,q,opt,x,tot; 11 void dfs(int x) 12 { 13 size[x]=1; 14 if (son[x].l) dfs(son[x].l); 15 num[++tot]=x; numl[x]=tot; 16 if (son[x].r) dfs(son[x].r); 17 sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo; 18 f[x]=((f[son[x].l]*f[son[x].r])%mo*sum[x])%mo; 19 size[x]+=size[son[x].l]+size[son[x].r]; 20 } 21 void build(int dep,int l,int r) 22 { 23 tree[dep].l=l; tree[dep].r=r; 24 if (l==r) 25 { 26 tree[dep].mul=sum[num[l]]; 27 return; 28 } 29 int mid=(l+r)/2; 30 build(dep*2,l,mid); 31 build(dep*2+1,mid+1,r); 32 tree[dep].mul=(tree[dep*2].mul*tree[dep*2+1].mul)%mo; 33 } 34 void change(int dep,int l,int r,int x,int y) 35 { 36 if (l==r) 37 { 38 tree[dep].mul=y; 39 return; 40 } 41 int mid=(l+r)/2; 42 if (mid>=x) change(dep*2,l,mid,x,y); 43 else change(dep*2+1,mid+1,r,x,y); 44 tree[dep].mul=(tree[dep*2].mul*tree[dep*2+1].mul)%mo; 45 } 46 void mul(int dep,int l,int r,int x,int y) 47 { 48 if (l==x&&y==r) 49 { 50 ans*=tree[dep].mul; 51 ans=ans%mo; 52 return; 53 } 54 int mid=(l+r)/2; 55 if (y<=mid) mul(dep*2,l,mid,x,y); 56 else if (x>mid) mul(dep*2+1,mid+1,r,x,y); 57 else mul(dep*2,l,mid,x,mid),mul(dep*2+1,mid+1,r,mid+1,y); 58 } 59 int rrotate(int x) 60 { 61 int y=son[x].l; 62 if (son[fa[x]].l==x) son[fa[x]].l=y; else son[fa[x]].r=y; 63 int u=size[y]; 64 size[y]=size[x]; 65 size[x]=size[x]-u+size[son[y].r]; 66 fa[son[y].r]=x; 67 fa[y]=fa[x]; 68 fa[x]=y; 69 son[x].l=son[y].r; 70 son[y].r=x; 71 sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo; 72 change(1,1,n,numl[x],sum[x]); 73 sum[y]=(sum[son[y].l]+sum[son[y].r]+a[y])%mo; 74 change(1,1,n,numl[y],sum[y]); 75 } 76 int lrotate(int x) 77 { 78 int y=son[x].r; 79 if (son[fa[x]].l==x) son[fa[x]].l=y; else son[fa[x]].r=y; 80 int u=size[y]; 81 size[y]=size[x]; 82 size[x]=size[x]-u+size[son[y].l]; 83 fa[son[y].l]=x; 84 fa[y]=fa[x]; 85 fa[x]=y; 86 son[x].r=son[y].l; 87 son[y].l=x; 88 sum[x]=(sum[son[x].l]+sum[son[x].r]+a[x])%mo; 89 change(1,1,n,numl[x],sum[x]); 90 sum[y]=(sum[son[y].l]+sum[son[y].r]+a[y])%mo; 91 change(1,1,n,numl[y],sum[y]); 92 } 93 int main() 94 { 95 //freopen("splay.in","r",stdin); 96 //freopen("splay.out","w",stdout); 97 scanf("%d%d",&n,&q); 98 f[0]=1; 99 for (int i=0;i<2000010;i++) tree[i].mul=1; 100 for (int i=1;i<=n;i++) 101 { 102 scanf("%d%d%d",&a[i],&son[i].l,&son[i].r); 103 f[i]=1; 104 fa[son[i].l]=i; fa[son[i].r]=i; 105 } 106 dfs(1); 107 build(1,1,n); 108 for (int i=1;i<=q;i++) 109 { 110 scanf("%d%d",&opt,&x); 111 if (opt==0) if (son[x].l) rrotate(x); 112 if (opt==1) if (son[x].r) lrotate(x); 113 if (opt==2) 114 { 115 ans=1; 116 mul(1,1,n,numl[x]-size[son[x].l],numl[x]+size[son[x].r]); 117 printf("%lld\n",ans); 118 } 119 } 120 return 0; 121 }