zoukankan      html  css  js  c++  java
  • cf276E 两棵线段树分别维护dfs序和bfs序,好题回头再做

    搞了一晚上,错了,以后回头再来看

    /*
    对于每次更新,先处理其儿子方向,再处理其父亲方向
    处理父亲方向时无法达到根,那么直接更新
    如果能达到根,那么到兄弟链中去更新,使用bfs序
    最后,查询结点v的结果就是dfs序线段树上的查询值+bfs线段树上的查询值
    */
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    #define maxn 150005
    int n,q;
    vector<int> mp[maxn];
    
    struct node{
        int u,depth;
    }now,nex;
    int depthL[maxn];//深度为i的下标最小的点
    int depthR[maxn];//深度为i的下标最大的点
    int num[maxn];//bfs序 
    int vis[maxn];
    
    int L[maxn];//dfs入序
    int R[maxn];//某结点为根的最大深度
    int dist[maxn];
    int cnt;
    void Dfs(int u,int from,int dis){
        L[u]=++cnt;
        dist[u]=dis;
        for(int i=0;i<mp[u].size();i++){
            int v=mp[u][i];
            if(v==from) continue;
            Dfs(v,u,dis+1);
        }
        R[u]=cnt;
    }
    //处理bfs序的方法
    void Bfs(){
        int tot=0;
        queue<node>s;
        now.u=1,now.depth=0;
        s.push(now);
        memset(depthL,-1,sizeof depthL);
        memset(depthR,0,sizeof depthR);
        memset(vis,0,sizeof vis);
        vis[1]=1;
        while(!s.empty()){
            tot++;
            now=s.front();
            s.pop();
            num[now.u]=tot;
            if(depthL[now.depth==-1])
                depthL[now.depth]=num[now.u];
            depthR[now.depth]=max(depthR[now.depth],num[now.u]);
            for(int i=0;i<mp[now.u].size();i++){
                int v=mp[now.u][i];
                if(vis[v]==0){
                    vis[v]=1;
                    nex.u=v;
                    nex.depth=now.depth+1;
                    s.push(nex);
                }
            }
        }
    }
    //第一棵线段树处理dfs上的修改和查询,因为所有的子树都是链,其dfs连续,所以直接用线段树区间更新
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int tree[maxn<<2];
    int flag[maxn<<2];
    inline void pushup(int rt){
        tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    }
    inline void pushdown(int l,int r,int rt){
        if(flag[rt]){
            int m=l+r>>1;
            flag[rt<<1]+=flag[rt];
            tree[rt<<1]=(m-l+1)*flag[rt];
            tree[rt<<1|1]=(r-m)*flag[rt];
            flag[rt]=0;
        }
    }
    void build(int l,int r,int rt){
        tree[rt]=flag[rt]=0;
        if(l==r) return;
        int m=l+r>>1;
        pushdown(l,r,rt);
        build(lson);
        build(rson);
        pushup(rt);
    }
    void update(int L,int R,int c,int l,int r,int rt){
        if(L<=l && R>=r){
            tree[rt]+=(r-l+1)*c;
            flag[rt]+=c;
            return;
        }
        int m=l+r>>1;
        pushdown(l,r,rt);
        if(L<=m) update(L,R,c,lson);
        if(R>m) update(L,R,c,rson);
        pushup(rt);
    }
    //是单点查询
    int query(int p,int l,int r,int rt){
        if(l==r) return tree[rt];
        int m=l+r>>1;
        pushdown(l,r,rt);
        if(p<=m) return query(p,lson);
        if(p>m) return query(p,rson);
        pushup(rt);
    }
    
    //第二棵线段树用来处理bfs上的修改和查询
    //bfs序线段树也是通过访问顺序维护信息
    int sum[maxn<<2];
    int flag2[maxn<<2];
    inline void pushup2(int rt){
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    inline void pushdown2(int l,int r,int rt){
        if(flag2[rt]){
            int m=l+r>>1;
            flag2[rt>>1]+=flag2[rt];
            flag2[rt>>1|1]+=flag2[rt];
            sum[rt>>1]+=(m-l+1)*flag2[rt];
            sum[rt>>1|1]+=(r-m)*flag2[rt];
            flag2[rt]=0;
        }
    }
    void build2(int l,int r,int rt){
        sum[rt]=flag2[rt]=0;
        if(l==r) return;
        int m=l+r>>1;
        pushdown2(l,r,rt);
        build(lson);
        build(rson);
        pushup2(rt);
    }
    void update2(int L,int R,int c,int l,int r,int rt){
        if(L<=l && R>=r){
            sum[rt]+=(r-l+1)*c;
            flag2[rt]+=c;
            return;
        }
        int m=l+r>>1;
        pushdown2(l,r,rt);
        if(L<=m) update(L,R,c,lson);
        if(R>m) update(L,R,c,rson);
        pushup2(rt);
    }
    int query2(int p,int l,int r,int rt){
        if(l==r) return sum[rt];
        int m=l+r>>1;
        pushdown2(l,r,rt);
        if(p<=m) return query2(p,lson);
        if(p>m) return query2(p,rson);
        pushup2(rt);
    }
    
    int main(){
        while(scanf("%d%d",&n,&q)==2){
            for(int i=1;i<=n;i++)
                mp[i].clear();
            for(int i=1;i<=n-1;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                mp[x].push_back(y);
                mp[y].push_back(x);
            }
            cnt=0;
            Dfs(1,-1,0);
            Bfs();
            build(1,n,1);
            build2(1,n,1);
            while(q--){
                int op;
                scanf("%d",op);
                if(op==1){//查询结点x的值
                    int x;
                    scanf("%d",&x);
                    printf("%d
    ",query(L[x],1,n,1)+query2(num[x],1,n,1));
                }
                else {
                    int u,v,d;scanf("%d%d%d",&u,&v,&d);
                    if(u==1){//如果是根结点,直接在兄弟结点上更新
                        if(depthR[d]!=0)//这个深度是有节点的
                            update2(1,depthR[d],v,1,n,1);
                        else //这个深度没有结点了,整棵树更新
                            update2(1,n,v,1,n,1);
                        continue;
                    }
                    //如果不是根结点上更新
                    //先在dfs序上更新,注意
                    update(L[u],min(L[u]+d,R[u]),v,1,n,1);
                    if(d<dist[u])//如果根到u距离大于d,直接在链上更新
                        update(L[u]-d,L[u]-1,v,1,n,1);
                    else {
                        //先从根维护到u的父亲
                        update(L[u]-(dist[u]-1),L[u]-1,v,1,n,1);
                        update(L[u]-(dist[u]-1),min(L[u]-(dist[u]-1)+(d-dist[u]-1),R[u]),-v,1,n,1);//取消root到其兄弟结点相同深度的相应修改,因为接下去bfs序修改会重复 
                        if(depthR[d-dist[u]]!=0)//如果这个深度有结点
                            update2(1,depthR[d-dist[u]],v,1,n,1);
                        else
                            update2(1,n,v,1,n,1);
                    }
                }
            }
        }
    }
  • 相关阅读:
    Minimum Depth of Binary Tree leetcode java
    Maximum Depth of Binary Tree leetcode java
    Symmetric Tree leetcode java
    Same Tree leetcode java
    Binary Tree Postorder Traversal leetcode java
    Binary Tree Preorder Traversal leetcode java
    Binary Tree Inorder Traversal leetcode java
    Combinations leetcode java
    一键清除Centos iptables 防火墙所有规则
    阿里云centos7.7x64安装open,并配置ip转发和nat伪装
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9926270.html
Copyright © 2011-2022 走看看