• BZOJ 1984: 月下“毛景树” [树链剖分 边权]


    1984: 月下“毛景树”

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 1728  Solved: 531
    [Submit][Status][Discuss]

    Description

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    Input

    第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

    Output

    对于毛毛虫的每个询问操作,输出一个答案。

    Sample Input

    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop

    Sample Output

    9
    16

    【Data Range】
    1<=N<=100,000,操作+询问数目不超过100,000。
    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

    比较明显树链剖分
    问题边权怎么处理?
    转化成边下面的点的权值就行了
     
    因为修改操作是第几条边,所以保存mp点到边
     
    线段树set修改标记,add增加标记
    打set时清空add,打add时有set直接加set就行了
     
    注意:不要直接用书上的点的编号的权值作为线段树编号的权值,加一个fid[i]为线段树节点i在原图上的编号!!!!
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    #define lc o<<1
    #define rc o<<1|1
    #define m ((l+r)>>1)
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    const int N=2e5+5,INF=1e9+5;
    int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,u,v,ww,w[N],l,r,mp[N];//edge-->point
    char s[10];
    struct edge{
        int v,w,ne,id;
    }e[N<<1];
    int h[N],cnt;
    inline void ins(int u,int v,int w,int id){
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].id=id;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].w=w;e[cnt].id=id;e[cnt].ne=h[v];h[v]=cnt;
    }
    int tid[N],fa[N],top[N],tot,deep[N],mx[N],size[N],fid[N];
    void dfs(int u){
        size[u]=1;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u]) continue;
            w[v]=e[i].w;mp[e[i].id]=v;
            fa[v]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[mx[u]]<size[v]) mx[u]=v;
        }
    }
    void dfs(int u,int anc){
        if(!u) return;
        tid[u]=++tot;fid[tot]=u;
        top[u]=anc;
        dfs(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
        }
    }
    
    struct node{
        int mx,set,add;
        node():set(-1),add(0){}
    }t[N<<2];
    inline void merge(int o){
        t[o].mx=max(t[lc].mx,t[rc].mx);
    }
    inline void paintset(int o,int v){
        t[o].set=t[o].mx=v;
        t[o].add=0;
    }
    inline void paintadd(int o,int v){
        if(t[o].set!=-1) t[o].set+=v,t[o].mx+=v;
        else t[o].add+=v,t[o].mx+=v;
    }
    inline void pushDown(int o){
        if(t[o].set!=-1){
            paintset(lc,t[o].set);
            paintset(rc,t[o].set);
            t[o].set=-1;
        }
        if(t[o].add){
            paintadd(lc,t[o].add);
            paintadd(rc,t[o].add);
            t[o].add=0;
        }
    }
    void build(int o,int l,int r){
        if(l==r) t[o].mx=w[fid[l]];
        else{
            build(lson);
            build(rson);
            merge(o);
        }
    }
    void segcha(int o,int l,int r,int p,int v){
        if(l==r) t[o].mx=v;
        else{
            pushDown(o);
            if(p<=m) segcha(lson,p,v);
            else segcha(rson,p,v); 
            merge(o);
        }
    }
    void segcov(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) paintset(o,v);
        else{
            pushDown(o);
            if(ql<=m) segcov(lson,ql,qr,v);
            if(m<qr) segcov(rson,ql,qr,v);
            merge(o);
        }
    }
    void segadd(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr) paintadd(o,v);
        else{
            pushDown(o);
            if(ql<=m) segadd(lson,ql,qr,v);
            if(m<qr) segadd(rson,ql,qr,v);
            merge(o);
        }
    }
    int segmx(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[o].mx;
        else{
            pushDown(o);
            int mx=-INF;
            if(ql<=m) mx=max(mx,segmx(lson,ql,qr));
            if(m<qr) mx=max(mx,segmx(rson,ql,qr));
            return mx;
        }
    }
    
    void add(int x,int y,int v){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            segadd(1,1,n,tid[top[x]],tid[x],v);
            x=fa[top[x]]; 
        }
        
        if(tid[x]>tid[y]) swap(x,y);
        if(x!=y) segadd(1,1,n,tid[x]+1,tid[y],v);//bian quan
    }
    void cover(int x,int y,int v){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            segcov(1,1,n,tid[top[x]],tid[x],v);
            x=fa[top[x]]; 
        }
        
        if(tid[x]>tid[y]) swap(x,y);
        if(x!=y) segcov(1,1,n,tid[x]+1,tid[y],v);//bian quan
    }
    int query(int x,int y){
        int mx=-INF;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            mx=max(mx,segmx(1,1,n,tid[top[x]],tid[x]));
            x=fa[top[x]];
        }
        if(tid[x]>tid[y]) swap(x,y);
        if(x!=y) mx=max(mx,segmx(1,1,n,tid[x]+1,tid[y]));
        return mx;
    }
    int main(){
        n=read();
        for(int i=1;i<=n-1;i++) u=read(),v=read(),ww=read(),ins(u,v,ww,i);
        dfs(1);dfs(1,1);
        build(1,1,n);
        while(true){
            scanf("%s",s);
            if(s[0]=='S') break;
            else if(s[1]=='h') l=read(),v=read(),segcha(1,1,n,tid[mp[l]],v);
            else if(s[1]=='o') l=read(),r=read(),v=read(),cover(l,r,v);
            else if(s[1]=='d') l=read(),r=read(),v=read(),add(l,r,v);
            else l=read(),r=read(),printf("%d
    ",query(l,r));
        }
    }
     
  • 相关阅读:
    有道词典_每日一句_2020/06
    有道词典_每日一句_2020/05
    有道词典_每日一句_2020/04
    有道词典_每日一句_2020/03
    Vue的模板语法之指令1——Vue学习笔记(3)
    Vue的模板语法之插值——Vue学习笔记(2)
    Vue的基本使用——Vue学习笔记(1)
    有道词典_每日一句_2020/02
    有道词典_每日一句_2020/01
    微信小程序 真机调试警告:Some selectors are not allowed in component wxss
  • 原文地址:https://www.cnblogs.com/candy99/p/6218252.html
Copyright © 2020-2023  润新知