给定一棵有根树,每个点上有一个固定不变的权值,每个点的sum值定义为以它为根的子树上的点的权值的和。现有3个操作,分别是对某个点左旋,对某个点右旋,以及查询某个点为根的子树的sum值的积。
因为左旋右旋操作对树的中序遍历不进行变动,所以我们把这棵树的中序遍历写成一个序列,那么以某个点为根的子树即为这个序列的一个区间。
左旋和右旋只会造成两个点的sum值改变,只会造成两个点影响的区间的改变。所以记录每个点的sum值,他以他为根的子树的在序列中的区间两端即可。
只需要点修改sum值和区间查询sum值的积,树状数组和线段树均可,不过树状数组要求逆元...
#pragma comment (linker,"/STACK:102400000,102400000")
#include <cstdio>
const int mod=1000000007;
struct Node {
int ls,rs,f,w,l,r,sum,dfn;
};
struct SeqNode {
SeqNode *ls,*rs;
int pro;
};
SeqNode b[200000];
SeqNode *bp,*seqRoot;
Node a[100001];
int realNode[100001];
int n,m,root,dfn;
void update(int i) {
a[i].sum=a[i].w;
if (a[i].ls) {
a[i].l=a[a[i].ls].l;
a[i].sum=(a[i].sum+a[a[i].ls].sum)%mod;
} else a[i].l=a[i].dfn;
if (a[i].rs) {
a[i].r=a[a[i].rs].r;
a[i].sum=(a[i].sum+a[a[i].rs].sum)%mod;
} else a[i].r=a[i].dfn;
//if ((a[i].ls&&a[a[i].ls].r+1!=a[i].dfn)||(a[i].rs&&a[a[i].rs].l!=a[i].dfn+1)||a[i].l>a[i].r) {
//printf("Error: Node %d, dfn %d, ls %d, rs %d, l %d, r %d\n",i,a[i].dfn,a[i].ls,a[i].rs,a[i].l,a[i].r);
//if (a[i].ls) printf(" LsNode: %d %d\n",a[a[i].ls].l,a[a[i].ls].r);
//if (a[i].rs) printf(" RsNode: %d %d\n",a[a[i].rs].l,a[a[i].rs].r);
//}
//printf("Node %d: %d %d %d\n",i,a[i].l,a[i].r,a[i].sum);
}
void dfs(int i) {
if (a[i].ls) dfs(a[i].ls);
realNode[dfn]=i;
a[i].dfn=dfn++;
if (a[i].rs) dfs(a[i].rs);
update(i);
}
SeqNode *makeTree(int l,int r) {
SeqNode *ans=bp++;
if (l==r) {
ans->ls=ans->rs=NULL;
ans->pro=a[realNode[l]].sum;
} else {
int t=(l+r)/2;
ans->ls=makeTree(l,t);
ans->rs=makeTree(t+1,r);
ans->pro=((long long)ans->ls->pro*ans->rs->pro)%mod;
}
return ans;
}
int get(SeqNode *from,int l,int r,int ll,int rr) {
//printf("get: %d %d %d %d\n",l,r,ll,rr);
if (l==ll&&r==rr) return from->pro;
int t=(l+r)/2;
if (rr<=t) return get(from->ls,l,t,ll,rr);
else if (t<ll) return get(from->rs,t+1,r,ll,rr);
else return (long long)get(from->ls,l,t,ll,t)*get(from->rs,t+1,r,t+1,rr)%mod;
}
void set(SeqNode *from,int l,int r,int i,int x) {
if (l==r) from->pro=x;
else {
int t=(l+r)/2;
if (i<=t) set(from->ls,l,t,i,x);
else set(from->rs,t+1,r,i,x);
from->pro=(long long)from->ls->pro*from->rs->pro%mod;
}
}
int main() {
int t,tt,i;
scanf("%d",&t);
for (tt=1;tt<=t;tt++) {
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) {
a[i].f=a[i].ls=a[i].rs=0;
}
for (i=1;i<=n;i++) {
int w,x,y;
scanf("%d%d%d",&w,&x,&y);
a[i].w=w; a[i].ls=x; a[i].rs=y;
if (x) a[x].f=i;
if (y) a[y].f=i;
}
dfn=1;
for (i=1;i<=n;i++) if (a[i].f==0) root=i;
dfs(root);
bp=b;
seqRoot=makeTree(1,n);
printf("Case #%d:\n",tt);
for (i=0;i<m;i++) {
int p,x;
scanf("%d%d",&p,&x);
if (p==0) {
//printf("Right rotation start:\n");
if (a[x].ls) {
int y=a[x].ls;
int f=a[x].f;
a[y].f=f;
a[x].f=y;
a[a[y].rs].f=x;
a[x].ls=a[y].rs;
a[y].rs=x;
update(x);
update(y);
if (f!=0) {
if (x==a[f].ls) a[f].ls=y;
else a[f].rs=y;
}
set(seqRoot,1,n,a[x].dfn,a[x].sum);
set(seqRoot,1,n,a[y].dfn,a[y].sum);
}
//printf("Right rotation end:\n");
} else if (p==1) {
//printf("Left rotation start:\n");
if (a[x].rs) {
int y=a[x].rs;
int f=a[x].f;
a[y].f=f;
a[x].f=y;
a[a[y].ls].f=x;
a[x].rs=a[y].ls;
a[y].ls=x;
update(x);
update(y);
if (f!=0) {
if (x==a[f].ls) a[f].ls=y;
else a[f].rs=y;
}
set(seqRoot,1,n,a[x].dfn,a[x].sum);
set(seqRoot,1,n,a[y].dfn,a[y].sum);
}
//printf("Left rotation end:\n");
} else {
printf("%d\n",get(seqRoot,1,n,a[x].l,a[x].r));
}
}
}
return 0;
}