zoukankan      html  css  js  c++  java
  • HDU 4942 Game on S♂play(线段树、模拟、扩栈)

    比赛的时候想到这题的大概做法,但由于卡别的水题。。。就赛后做了。。。

    题意:给一个二叉树,每个结点有一个w[i],有3种操作,0 x表示左旋x,1 x表示右旋x,3 x表示询问x结点的价值,其中,价值为x子树结点的累加价值的累乘,其中,结点的累加价值为结点子树的Σw[i]。即询问是,∏Σw。

    好像题意被我说得好渣好乱。。。。还是忽略上面2行吧。。。

    首先,左旋右旋不影响中序遍历的index,即,可以把题目那2个图进行中序遍历,结果都是αXβYγ。由此,可以建立线段树。

    而左旋右旋的过程模拟即可,可画示意图,将所有改变的一一写上。

    要注意的是记得要改原本x跟父亲那条边,一开始没这个然后RE。。。。

    #pragma comment (linker,"/STACK:102400000,102400000")
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    #define ll long long
    #define maxn 100010
    #define mod 1000000007
    
    int son[maxn][2];
    int fa[maxn];
    int idx[maxn];
    int real[maxn];
    int lr[maxn][2];
    int w[maxn];
    ll val[maxn];
    ll mul[maxn<<2];
    void dfs(int x,int& dfn){
        val[x] = w[x];
        if(son[x][0]) dfs(son[x][0],dfn), lr[x][0]=lr[son[x][0]][0], val[x]+=val[son[x][0]];
        else lr[x][0]=dfn+1;
        idx[x] = ++dfn;
        real[dfn]=x;
        if(son[x][1]) dfs(son[x][1],dfn), lr[x][1]=lr[son[x][1]][1], val[x]+=val[son[x][1]];
        else lr[x][1]=dfn;
        val[x]%=mod;
    }
    void pushUp(int u){
        mul[u] = mul[u<<1]*mul[u<<1|1]%mod;
    }
    void build(int u,int l,int r){
        if(l==r){
            mul[u] = val[real[l]];
            return ;
        }
        int mid = (l+r)>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushUp(u);
    }
    ll query(int u,int l,int r,int L,int R){
        if(l==L&&r==R) return mul[u];
        int mid = (l+r)>>1;
        if(R<=mid) return query(u<<1,l,mid,L,R);
        else if(L>mid) return query(u<<1|1,mid+1,r,L,R);
        return query(u<<1,l,mid,L,mid)*query(u<<1|1,mid+1,r,mid+1,R)%mod;
    }
    void update(int u,int l,int r,int pos,ll v){
        if(l==r){
            mul[u] = v;
            return ;
        }
        int mid = (l+r)>>1;
        if(pos<=mid) update(u<<1,l,mid,pos,v);
        else update(u<<1|1,mid+1,r,pos,v);
        pushUp(u);
    }
    void LR(int x,int op,int n){
        if(son[x][op]==0) return ;
        int y = son[x][op];
        int bb = son[y][op^1], cc=son[y][op];
        son[x][op]=bb;
        fa[bb]=x;
        int xx=fa[x];
        if(son[xx][0]==x) son[xx][0]=y;
        else son[xx][1]=y;
        fa[y]=xx;
        son[y][op^1]=x;
        fa[x]=y;
        if(bb) lr[x][op] = lr[bb][op];
        else lr[x][op] = idx[x];
        lr[y][op^1] = lr[x][op^1];
        if(bb) val[x] = val[x]-val[y]+val[bb];
        else val[x] = val[x]-val[y];
        if(cc) val[y] = val[x]+val[cc]+w[y];
        else val[y] = val[x]+w[y];
        update(1,1,n,idx[x],val[x]);
        update(1,1,n,idx[y],val[y]);
    }
    int main(){
        int t,n,m,ca=0;
        scanf("%d",&t);
        while(t--){
            printf("Case #%d:
    ",++ca);
            scanf("%d%d",&n,&m);
            memset(fa,0,sizeof(fa));
            son[0][0]=son[0][1]=0;
            for(int i=1;i<=n;++i){
                scanf("%d%d%d",w+i,son[i],son[i]+1);
                fa[son[i][0]]=fa[son[i][1]]=i;
            }
            int dfn=0;
            dfs(1,dfn);
            build(1,1,n);
            for(int i=0;i<m;++i){
                int op,x;
                scanf("%d%d",&op,&x);
                if(op==2) printf("%I64d
    ",query(1,1,n,lr[x][0],lr[x][1]));
                else LR(x,op,n);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    js Object.freeze()
    js Object.seal()
    js数字千分位,三种写法,,拿走。。。
    nodejs mongoose连接mongodb报错,command find requires authentication
    nodejs express 服务代理
    容器监控之cadvisor
    kubernetes 集群卸载清理
    解决目录太大-建立软链接
    与运算(&)、或运算(|)、异或运算(^)
    jpa中将查询的字段返回为Map键值对类型
  • 原文地址:https://www.cnblogs.com/nextbin/p/3910923.html
Copyright © 2011-2022 走看看