zoukankan      html  css  js  c++  java
  • hdu 4942

    Game on S♂play

    Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 942    Accepted Submission(s): 208


    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
     
     
    析:给一颗n个节点的树,每个节点附带一个权值wi,而每个节点拥有兴趣值为其所有子树权值之和,要求支持三种操作:
    1.对节点x右旋
    2.对节点x左旋
    3.查询指定节点所有子树兴趣值之积
     
    说到左右旋,首先可以想到平衡树,可知平衡树左右旋仍满足中序遍历序列不变,每个节点与子树处于同一段连续序列中,故每次左右旋仅改变两个节点,其他节点不受影响,可以预处理每个节点的兴趣值以及兴趣值之积,
    并依次按中序遍历顺序指定每个节点的序号,以及每个点的子树边界区间,然后用线段树维护改变的两个点上的路径即可,注意维护子树左右边界值
     
    注意:模运算后,子树权值和即节点兴趣值可能为负数,故需要加上模值后再取模
     
    #pragma comment (linker,"/STACK:102400000,102400000")
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mod 1000000007
    using namespace std;
    const int N = 101015;
    int t, n, m, ans;
    int l[N], r[N], L[N], R[N], C[N], f[N];
    ll w[N], s[N], sum[N], prd[N<<2];
    inline void Maintain(int rt){
        L[rt] = R[rt] = C[rt];
        if(l[rt]){
            L[rt] = min(L[rt], L[l[rt]]);
            R[rt] = max(R[rt], R[l[rt]]);
        }
        if(r[rt]){
            L[rt] = min(L[rt], L[r[rt]]);
            R[rt] = max(R[rt], R[r[rt]]);
        }
    }
    inline ll dfs(int cur){
        s[cur] = w[cur];
        if(l[cur]){
            s[cur] += dfs(l[cur])%mod;
        }
        L[cur] = R[cur] = C[cur] = ans++;
        if(r[cur]){
            s[cur] += dfs(r[cur])%mod;
        }
        Maintain(cur);
        return sum[C[cur]] = s[cur];
    }
    inline void Build(int rt, int l, int r){
        if(l == r){
            prd[rt] = sum[l];
            return;
        }
        int m = (l+r)>>1;
        Build(rt<<1, l, m);
        Build(rt<<1|1, m+1, r);
        prd[rt] = prd[rt<<1]*prd[rt<<1|1]%mod;
    }
    inline void Modify(int rt, int l, int r, int pos, ll val){
        if(l == r){
            prd[rt] = val;
            return;
        }
        int m = (l+r)>>1;
        if(pos <= m) Modify(rt<<1, l, m, pos, val);
        else Modify(rt<<1|1, m+1, r, pos, val);
        prd[rt] = prd[rt<<1]*prd[rt<<1|1]%mod;
    }
    inline ll Query(int rt, int l, int r, int L, int R){
        if(L <= l && r <= R)
            return prd[rt];
        ll res = 1;
        int m = (l+r)>>1;
        if(L <= m)
            res = res*Query(rt<<1, l, m, L, R)%mod;
        if(R > m)
            res = res*Query(rt<<1|1, m+1, r, L, R)%mod;
        return res;
    }
    
    int main(){
        scanf("%d", &t);
        for (int i = 1; i <= t; i ++) {
            printf("Case #%d:
    ", i);
            f[0] = f[1] = 0;        //wa点,必须置零
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%lld%d%d", &w[i], &l[i], &r[i]);
                f[l[i]] = i; f[r[i]] = i;
            }
            int x, y, Q;
            ans = 1, dfs(1); Build(1, 1, n);
            for(int i = 1; i <= m; i++) {
                scanf("%d%d", &Q, &x);
                if(!Q){
                    y = l[x];
                    if(!y) continue;
                    s[x] = (s[x]+s[r[y]]-s[y]+mod)%mod; //wa点,可能出现负数
                    s[y] = (s[y]+s[x]-s[r[y]]+mod)%mod;
                    Modify(1, 1, n, C[x], s[x]);
                    Modify(1, 1, n, C[y], s[y]);
                    if(x == l[f[x]]){
                        l[f[x]] = y;
                    }else{
                        r[f[x]] = y;
                    }
                    f[y] = f[x], l[x] = r[y], f[r[y]] = x;
                    r[y] = x, f[x] = y;
                    Maintain(x); Maintain(y);
                }else if(Q == 1){
                    y = r[x];
                    if(!y) continue;
                    s[x] = (s[x]+s[l[y]]-s[y]+mod)%mod; //wa点,可能出现负数
                    s[y] = (s[y]+s[x]-s[l[y]]+mod)%mod;
                    Modify(1, 1, n, C[x], s[x]);
                    Modify(1, 1, n, C[y], s[y]);
                    if (x == l[f[x]]){
                        l[f[x]] = y;
                    }else{
                        r[f[x]] = y;
                    }
                    f[y] = f[x], r[x] = l[y], f[l[y]] = x;
                    l[y] = x; f[x] = y;
                    Maintain(x); Maintain(y);
                }else {
                    printf("%lld
    ", Query(1, 1, n, L[x], R[x]));
                }
            }
        }
    }
    View Code
  • 相关阅读:
    Java 常提到的自然序(Natural Ordering)
    设计模式(三)行为模式
    设计模式(二)结构模式
    设计模式(一)建造者模式
    设计模式的概念以及面向对象设计原则
    Java源码 HashMap<K,V>
    mybatis注解使用
    spring整合mybatis
    数据库中的表批量映射为对象
    返回用户提交的图像工具类
  • 原文地址:https://www.cnblogs.com/microcodes/p/12803539.html
Copyright © 2011-2022 走看看