hdu 4942 Game on S♂play 线段树

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 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 2
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 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值