题目大意
给出一棵二叉树,
有左旋和右旋操作,
询问某个点子树的size的乘积。
题解
平衡树有一个很重要的性质:
无论怎样旋转,这棵树的中序遍历是一定不会变的。
而一个节点的子树在中序遍历里面是连续的一段,
也就是要求中序遍历中间某一段连续的size的乘积。
而每次旋转操作,无论左旋还是右旋,都只会改变两个点,
每次旋转的时候就修改两个点的size,左右儿子,以及它子树在中序遍历中对于的区间,
用线段树维护size的乘积,单点修改,查询区间。
code
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 200003
#define M 103
#define db double
#define P putchar
#define G getchar
#define mo 1000000007
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
ll g[N*4],s[N];
int f[N],son[2][N],v[N],dfn[N],l[N],r[N];
int n,q,opt,x,id,opl,opr,ops,pos[N];
void build(int x,int l,int r)
{
if(l==r)
{
g[x]=s[dfn[l]];
return;
}
int m=(l+r)>>1;
build(x<<1,l,m);
build((x<<1)|1,m+1,r);
g[x]=g[x<<1]*g[(x<<1)|1]%mo;
}
void find(int x,int l,int r)
{
if(opl<=l && r<=opr)
{
ops=ops*g[x]%mo;
return;
}
int m=(l+r)>>1;
if(opl<=m)find(x<<1,l,m);
if(m<opr)find((x<<1)|1,m+1,r);
}
void work(int x,int l,int r)
{
if(l==r)
{
g[x]=s[dfn[l]];
return;
}
int m=(l+r)>>1;
if(opl<=m)work(x<<1,l,m);
else work((x<<1)|1,m+1,r);
g[x]=g[x<<1]*g[(x<<1)|1]%mo;
}
void rotate(int x,int w)//1:l 0:r
{
int y=son[w][x];
if(!y)return;
s[x]=(s[x]-s[y]+s[son[1-w][y]]+mo)%mo;
s[y]=(s[x]+s[son[w][y]]+v[y]+mo)%mo;
f[son[1-w][y]]=x;
son[w][x]=son[1-w][y];
f[y]=f[x];son[son[1][f[x]]==x?1:0][f[x]]=y;
f[x]=y;son[1-w][y]=x;
l[x]=son[0][x]?l[son[0][x]]:pos[x];r[x]=son[1][x]?r[son[1][x]]:pos[x];
l[y]=son[0][y]?l[son[0][y]]:pos[y];r[y]=son[1][y]?r[son[1][y]]:pos[y];
opl=pos[x];work(1,1,n);
opl=pos[y];work(1,1,n);
}
void dfs(int x)
{
if(!x)return;
l[x]=id+1;
dfs(son[0][x]);
dfn[++id]=x;pos[x]=id;
dfs(son[1][x]);
r[x]=id;
}
int main()
{
read(n);read(q);
for(int i=1;i<=n;i++)
read(v[i]),read(son[0][i]),read(son[1][i]),
f[son[0][i]]=i,f[son[1][i]]=i;
s[0]=f[0]=0;
for(int i=n;i;i--)
s[i]=(s[son[0][i]]+s[son[1][i]]+v[i])%mo;
dfs(1);build(1,1,n);
for(;q;q--)
{
read(opt);read(x);
if(opt==2)
{
ops=1;opl=l[x];opr=r[x];
find(1,1,n);
write(ops);P('\n');
}else rotate(x,opt);
}
return 0;
}