P4315 month of "Mao Tree View" (Tree chain split gon + + + interval coverage zone interval maximum value plus +)

Topic links: https://www.luogu.org/problem/P4315

Subject to the effect:

N nodes and N-1 Article branches, but there is no node plush fruit, fruit fur on the branches are long. But the tree, "King Mao tree" has a sense of magic, you can change the number of branches on his hairy fruit:
Change kw: to change the number of branches on the k-th is w a plush fruit.
Cover uvw: the number of branches on the plush between node u and node v are changed to the fruit of w.
Add uvw: the number of branches on the plush between node u and node v fruit have increased the w. As the caterpillar is very greedy, so he will have the following inquiry:
Max uv: ask the branch between node u and node v hairy fruit up to the number of how many.

 

Problem-solving ideas: a tree right side sectional title, the code is very long, it is still a little complicated debugging.

Note the following points:

1. The right side can be converted to the right point, because each child node of the parent node of the leading edge is unique, so it can be on the right side of each side edge being connected to a child node (in the tree may be the cross-sectional the first dfs completed)

2. Modify the weight on the same chain, the chain ends to be noted that the point lca can not be modified , because the corresponding edge weights lca this is not a chain.

3.Change operation is to modify the k-th branch, k is sequentially read , the storage side of the tree is bidirectional, so to read k multiplied during operation of the latter two.

4. If push-down marker when covering marks do not forget to add the tag to clear .

 

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100005;
int tot,cnt,head[maxn],n,m,v[maxn];
ll tree[maxn*4],lazy[maxn*4],cov[maxn*4];
int d[maxn],size[maxn],son[maxn],id[maxn],rk[maxn],fa[maxn],top[maxn];
//cov为覆盖标记,lazy为累加标记 
struct Edge{
    int u,v,w,next;
}edge[maxn<<1];
void add(int u,int v,int w){
    edge[++tot].v=v;
    edge[tot].u=u;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot;
}
void dfs1(int u,int pre){
    d[u]=d[pre]+1;
    fa[u]=pre;
    size[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int vv=edge[i].v;
        if(vv!=pre){
            dfs1(vv,u);
            size[u]+=size[vv];
            v[vv]=edge[i].w;  //边权转为点权 
            if(size[son[u]]<size[vv]) son[u]=vv;
        }
    }
}
void dfs2(int u,int tp){
    top[u]=tp,id[u]=++cnt,rk[cnt]=u;
    if(son[u]) dfs2(son[u],tp);  
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    }
}
void pushup(int rt){
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
void pushdown(int l,int r,int rt){
    if(cov[rt]!=-1){
        cov[rt<<1]=cov[rt<<1|1]=cov[rt];
        tree[rt<<1]=tree[rt<<1|1]=cov[rt];
        lazy[rt<<1]=lazy[rt<<1|1]=0; //将孩子节点的lazy标记清0 
        cov[rt]=-1;
    }
    if(lazy[rt]){
        tree[rt<<1]=tree[rt<<1]+lazy[rt];
        tree[rt<<1|1]=tree[rt<<1|1]+lazy[rt];
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void build(int l,int r,int rt){
    lazy[rt]=0;
    cov[rt]=-1;
    if(l==r){
        tree[rt]=v[rk[l]];
        return;
    }
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
void update1(int L,int R,int val,int l,int r,int rt){ //区间Cover和Change 
    if(L<=l&&R>=r){
        tree[rt]=val;
        cov[rt]=val;
        lazy[rt]=0; //将lazy标记清0 
        return;
    }
    int mid=l+r>>1;
    pushdown(mid-l+1,r-mid,rt);
    if(mid>=L) update1(L,R,val,l,mid,rt<<1);
    if(mid<R) update1(L,R,val,mid+1,r,rt<<1|1);
    pushup(rt);
}
void update2(int L,int R,int val,int l,int r,int rt){ //区间Add 
    if(L<=l&&R>=r){
        tree[rt]+=val;
        lazy[rt]+=val;
        return;
    }
    int mid=l+r>>1;
    pushdown(mid-l+1,r-mid,rt);
    if(mid>=L) update2(L,R,val,l,mid,rt<<1);
    if(mid<R) update2(L,R,val,mid+1,r,rt<<1|1);
    pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){ //区间求Max 
    if(L<=l&&R>=r) return tree[rt];
    int mid=l+r>>1; ll res=0;
    pushdown(mid-l+1,r-mid,rt);
    if(mid>=L) res=max(res,query(L,R,l,mid,rt<<1));
    if(mid<R) res=max(res,query(L,R,mid+1,r,rt<<1|1));
    return res;
}
void updates1(int x,int y,int val){ //Cover 
    while(top[x]!=top[y]){ 
        if(d[top[x]]<d[top[y]]) swap(x,y);
        update1(id[top[x]],id[x],val,1,n,1); 
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update1(id[x]+1,id[y],val,1,n,1); //不能更新lca所以是id[x]+1 
}
void updates2(int x,int y,int val){ //Add 
    while(top[x]!=top[y]){ 
        if(d[top[x]]<d[top[y]]) swap(x,y);
        update2(id[top[x]],id[x],val,1,n,1); 
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update2(id[x]+1,id[y],val,1,n,1); //不能更新lca所以是id[x]+1 
}
ll ask(int x,int y){ //求Max 
    ll res=0;
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]]) swap(x,y);
        res=max(res,query(id[top[x]],id[x],1,n,1));
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    res=max(res,query(id[x]+1,id[y],1,n,1));
    return res;
}
int main(){
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    cnt=0,tot=0;
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w); add(v,u,w);
    }
    dfs1(1,0),dfs2(1,1);
    build(1,n,1);
    while(true){
        char op[10];
        int x,l,r,rt,val;
        scanf("%s",op);
        if(op[1]=='t') break;
        if(op[1]=='h'){
            scanf("d% d% ",&x,&val); // Because undirected edges, so that x * 2 x article is represented sides 
            x = D [Edge [x * 2 ] .u]> D [Edge [x * 2 ] .v]? Edge [x * 2 ] .u: Edge [X * 2 ] .v; 
            Update1 (ID [X], ID [X], Val, . 1 , n-, . 1 );   // Change operation 
        } the else  IF (OP [ . 1 ] == ' O ' ) { 
            Scanf ( " % D% D% D " , & L, R & lt &, & Val); 
            updates1 (L, R & lt, Val); // Cover operating 
        } the else  IF (OP [ . 1 ] == 'd'){
            scanf("%d%d%d",&l,&r,&val);
            updates2(l,r,val); //Add操作 
        } else if(op[1]=='a'){
            scanf("%d%d",&l,&r);
            printf("%lld\n",ask(l,r)); //Max操作 
        }
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/zjl192628928/p/11301710.html