hdu 4942 Game on S♂play 线段树

来源:互联网 发布:java制表符 编辑:程序博客网 时间:2024/05/17 04:01

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.
 

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 nodex; 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
13 41 2 31 0 01 0 02 10 12 22 1
 

Sample Output
Case #1:362
Hint
As 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 1000000007struct 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;}


0 0