Game on S♂play
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 294 Accepted Submission(s): 52
Problem Description
Uncle Fang is learning Splay. When he heard about the rotate operation, he would like to play a game with Captain Chen. There is a tree with n nodes initially, and the node 1 is the root. The i-th nodes gets a weight of wi, and an attribute of interesting value defined as the sum of the weight of it’s descendants. Following are two operations in this tree:
1.do a rotation on a node x. The rotation is the common rotation in splay tree, it can be right-rotation or left-rotation, as demonstrated in the following picture. If it's impossible to rotate, just ignore it!
2.ask Captain Chen the product of interesting values of the nodes in a subtree rooted at node x.
1.do a rotation on a node x. The rotation is the common rotation in splay tree, it can be right-rotation or left-rotation, as demonstrated in the following picture. If it's impossible to rotate, just ignore it!
![](https://i-blog.csdnimg.cn/blog_migrate/6a1a5cd3c3e532dfb1b622c07021174d.jpeg)
2.ask Captain Chen the product of interesting values of the nodes in a subtree rooted at node x.
Input
There are several cases.The first line of the input contains a single integer T (T <= 30) which is the number of test cases.Then comes the T test cases .
For each case, the first line contains two integer numbers n and m(1<=n, m<=100000).
The following n lines describe the tree. In the i-th line, there was three number wi, xi, yi,(0<=w<=100000, 0<=x, y<=n) indicate the weight of node i, the left child of node i, and the right child of node i. If xi or yi equals to 0, it means node i has no such child.
And the following m lines describe the operations. There are two numbers p x in each line. If p is 0, it means do right-rotation on node x; If p is 1, it means do left-rotation on node x; if p is 2, it means ask the product of interesting values of the nodes in a subtree rooted at node x.
For each case, the first line contains two integer numbers n and m(1<=n, m<=100000).
The following n lines describe the tree. In the i-th line, there was three number wi, xi, yi,(0<=w<=100000, 0<=x, y<=n) indicate the weight of node i, the left child of node i, and the right child of node i. If xi or yi equals to 0, it means node i has no such child.
And the following m lines describe the operations. There are two numbers p x in each line. If p is 0, it means do right-rotation on node x; If p is 1, it means do left-rotation on node x; if p is 2, it means ask the product of interesting values of the nodes in a subtree rooted at node x.
Output
For the k-th test case, first output “Case #k:” in a separate line.Then for each query,output a single num in each line after mod 1000000007.
Sample Input
1 3 4 1 2 3 1 0 0 1 0 0 2 1 0 1 2 2 2 1
Sample Output
Case #1: 3 6 2HintAs the input data may cause the stack overflow if you use some recursion solution. Add #pragma comment (linker,"/STACK:102400000,102400000") in C++ language.
题意:给三个操作,左旋和右旋,就是把节点的左孩子或右孩子提到根上即可
查询:查询以x为跟的子树所有节点的欢乐值的成绩 欢乐值为这个节点为根的子树的节点个数
解法:看了解题报告才知道的。 左旋和右旋不影响树的中序遍历,所以可以用线段树做
用一次dfs中序遍历一次,给每个节点一个id,一颗子树的所有节点的编号一定是连续期间的
每次旋转操作的时候,只要修改两个点的信息,然后更新一下这两个点的欢乐值即可
#pragma comment (linker,"/STACK:102400000,102400000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 200007
#define ll long long
#define lc u<<1
#define rc (u<<1)+1
#define mod 1000000007
struct Node{
int l,r,fa,LL,rr;
ll val;
};
Node node[maxn];
Node tree[maxn*4];
int id[maxn],fid[maxn];
int w[maxn];
int cnt;
void updateNode(int u){
node[u].LL = node[u].rr = id[u],node[u].val = w[u];
if(node[u].l!=0){
node[u].LL = min(node[u].LL,node[node[u].l].LL),node[u].rr=max(node[u].rr,node[node[u].l].rr);
node[u].val += node[node[u].l].val;
}
if(node[u].r!=0){
node[u].LL = min(node[u].LL,node[node[u].r].LL),node[u].rr=max(node[u].rr,node[node[u].r].rr);
node[u].val += node[node[u].r].val;
}
}
void dfs(int u){
if(u == 0) return ;
dfs(node[u].l);
fid[cnt]=u;
id[u] = cnt++;
dfs(node[u].r);
updateNode(u);
}
void update(int u){
tree[u].val = tree[lc].val*tree[rc].val%mod;
}
void build(int u,int l,int r){
tree[u].l = l, tree[u].r=r;
if(l == r){
tree[u].val = node[fid[l]].val;
return ;
}
int mid = (l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
update(u);
}
void change(int u,int p,ll val){
if(tree[u].l == tree[u].r){
tree[u].val = val;
return ;
}
int mid = (tree[u].l+tree[u].r)/2;
if(mid >= p) change(lc,p,val);
else change(rc,p,val);
update(u);
}
ll query(int u,int l,int r){
if(tree[u].l == l && tree[u].r == r)
return tree[u].val ;
int mid = (tree[u].l+tree[u].r)/2;
if(mid >= r) return query(lc,l,r);
else if(mid<l) return query(rc,l,r);
else return query(lc,l,mid)*query(rc,mid+1,r)%mod;
}
void init(){
w[0] = 0,cnt=1;
memset(&node[0],0,sizeof(node[0]));
node[1].fa = 0;
}
void UP(int x,int f,int ff){
if(node[ff].l == f && ff) node[ff].l=x;
else if(node[ff].r == f && ff)node[ff].r = x;
node[f].fa = x;
node[x].fa = ff;
updateNode(f);
updateNode(x);
change(1,id[x],node[x].val);
change(1,id[f],node[f].val);
}
int main(){
int t,n,q,ope,x,ff,f;
scanf("%d",&t);
for(int tt=1;tt<=t;tt++){
scanf("%d %d",&n,&q);
init();
for(int i =1;i <= n;i++){
scanf("%d%d%d",&w[i],&node[i].l,&node[i].r);
if(node[i].l)node[node[i].l].fa=i;
if(node[i].r)node[node[i].r].fa=i;
}
dfs(1);
build(1,1,n);
printf("Case #%d:\n",tt);
while(q--){
scanf("%d%d",&ope,&x);
if(ope == 0 && node[x].l != 0){
x=node[x].l;f = node[x].fa ;ff = node[f].fa;
node[f].l = node[x].r;
node[node[x].r].fa=f;
node[x].r = f;
UP(x,f,ff);
}
if(ope == 1 && node[x].r != 0){
x=node[x].r;f=node[x].fa;ff=node[f].fa;
node[f].r = node[x].l;
node[node[x].l].fa=f;
node[x].l = f;
UP(x,f,ff);
}
if(ope == 2){
printf("%I64d\n",query(1,node[x].LL,node[x].rr)%mod);
}
}
}
return 0;
}