题目梗概
给出一棵树,定义一个节点的有趣值为该节点为根的树的权值和。
现在可以旋转一个节点,询问任意子树的有趣值之积。
解题思路
不管树怎么旋转,这棵树的中序遍历是不变的。
维护每个节点控制范围和有趣值。
用线段树维护有趣值的积。
#pragma comment (linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#define LL long long
#define maxn 100005
#define tt 1000000007
#define ls x<<1
#define rs (x<<1)+1
using namespace std;
struct jz{
int son[2],L,R,fa;
LL w;
}a[maxn],t[maxn*4];
int T,n,m,w[maxn],tot,id[maxn],h[maxn];
inline int _read(){
int num=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
return num;
}
inline int min(int x,int y){if (x<y) return x;return y;}
inline int max(int x,int y){if (x>y) return x;return y;}
void updata(int x){t[x].w=(t[ls].w*t[rs].w)%tt;}
void renew(int x){
a[x].L=a[x].R=id[x];a[x].w=w[x];
for (int i=0;i<2;i++) if (a[x].son[i]){
a[x].L=min(a[x].L,a[a[x].son[i]].L);a[x].R=max(a[x].R,a[a[x].son[i]].R);
a[x].w+=a[a[x].son[i]].w;
}
}
void DFS(int x){
if (!x) return;
DFS(a[x].son[0]);
id[x]=++tot;h[tot]=x;
DFS(a[x].son[1]);
renew(x);
}
void Build(int x,int L,int R){
t[x].L=L,t[x].R=R;
if (L==R){t[x].w=a[h[L]].w;return;}
int mid=L+(R-L>>1);
Build(ls,L,mid);Build(rs,mid+1,R);
updata(x);
}
void change(int x,int p,LL y){
if (t[x].L==t[x].R){t[x].w=y;return;}
int mid=t[x].L+(t[x].R-t[x].L>>1);
if (p<=mid) change(ls,p,y);else change(rs,p,y);
updata(x);
}
LL query(int x,int L,int R){
if (L==t[x].L&&R==t[x].R) return t[x].w;
int mid=t[x].L+(t[x].R-t[x].L>>1);
if (R<=mid) return query(ls,L,R);else
if (L>mid) return query(rs,L,R);else
return (query(ls,L,mid)*query(rs,mid+1,R))%tt;
}
void turn(int x,int d){
int t=a[x].son[d],ff=a[x].fa;
a[x].son[d]=a[t].son[d^1];a[a[t].son[d^1]].fa=x;a[t].son[d^1]=x;
if (ff) a[ff].son[x!=a[ff].son[0]]=t;
a[t].fa=ff;a[x].fa=t;
renew(x);renew(t);
change(1,id[x],a[x].w);change(1,id[t],a[t].w);
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
T=_read();
for (int t=1;t<=T;t++){
n=_read(),m=_read();
memset(a,0,sizeof(a));
for (int i=1;i<=n;i++){
w[i]=_read(),a[i].son[0]=_read(),a[i].son[1]=_read();
if (a[i].son[0]) a[a[i].son[0]].fa=i;
if (a[i].son[1]) a[a[i].son[1]].fa=i;
}
tot=0;DFS(1);Build(1,1,n);
printf("Case #%d:\n",t);
for (int i=1;i<=m;i++){
int y=_read(),x=_read();
if (y==2) printf("%lld\n",query(1,a[x].L,a[x].R)%tt);
if (y==0&&a[x].son[0]) turn(x,0);
if (y==1&&a[x].son[1]) turn(x,1);
}
}
}