bzoj1984 月下“毛景树”树链剖分 线段树

6 篇文章 0 订阅
3 篇文章 0 订阅

狠狠地吐槽一下csdn不知怎么编辑没保存客服还说没有修改记录尼玛 有空再写吧
题意:动态修改(add)边权 动态覆盖(cover)路径 动态询问路径最大值 N<=100000
题解:首先想象在一个线段上就是个裸的线段树……在树上就链剖嘛
cover和add分两个tag记标记
下传时有点麻烦 有cover的话就先传cover再传add 没有cover的话直接传add(开始没想清楚导致对拍了好久QAQ
还有就是边权需要转到点权上去 (u,v) && fa[v]==u then w(u,v)->val[v]
都是细节辣
本来150行的……然而输出查错……
应该提高一下代码能力 暴力写了也不短时间 查错了查了好久

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005;
struct E{int to,nxt,w;}edge[N*2];
struct EE{int u,v,w;}bian[N];
struct seg{int l,r,mx,add,cover;}tree[4*N];
int idx[N],tot=1,cnt,n;
int val[N],fa[N],son[N],size[N],dep[N],top[N],w[N],f[N];
void addedge(int from,int to,int w){
    edge[tot].to=to;edge[tot].w=w;edge[tot].nxt=idx[from];idx[from]=tot++;
}
void dfs1(int x,int f){
    for(int t=idx[x];t;t=edge[t].nxt){
        E e=edge[t];
        if(e.to!=f){
            val[e.to]=e.w;
            fa[e.to]=x;
            dep[e.to]=dep[x]+1;
            dfs1(e.to,x);
            if(size[son[x]]<size[e.to]) son[x]=e.to;
            size[x]+=size[e.to];
        }
    }
    size[x]++;
}
void dfs2(int x,int Top){
    w[x]=++cnt;f[cnt]=x;top[x]=Top;
    if(son[x]!=0) dfs2(son[x],Top);
    for(int t=idx[x];t;t=edge[t].nxt){
        E e=edge[t];
        if(e.to!=fa[x] && e.to!=son[x]) dfs2(e.to,e.to);
    }
}
void pushdown(int now){
    int add=tree[now].add;
    int cover=tree[now].cover;
    if(cover){
        tree[now<<1].cover=cover;
        tree[now<<1|1].cover=cover;
        tree[now<<1].mx=cover;
        tree[now<<1|1].mx=cover;
        tree[now<<1].add=0;
        tree[now<<1|1].add=0;
    }
    tree[now<<1].add+=add;
    tree[now<<1|1].add+=add;
    tree[now<<1].mx+=add;
    tree[now<<1|1].mx+=add;
    tree[now].add=0;tree[now].cover=0;
}
void pushup(int now){
    tree[now].mx=max(tree[now<<1].mx,tree[now<<1|1].mx);
}
void build(int now,int a,int b){
    tree[now].l=a;tree[now].r=b;
    int mid=(a+b)>>1;
    if(a==b){tree[now].mx=val[f[a]];return;}
    build(now<<1,a,mid);build(now<<1|1,mid+1,b);
    pushup(now);
}
void Cover(int now,int a,int b,int x){
    if(a>tree[now].r || b<tree[now].l) return;
    if(a<=tree[now].l && tree[now].r<=b){
        tree[now].cover=x;tree[now].add=0;
        tree[now].mx=x;return;
    }
    pushdown(now);
    Cover(now<<1,a,b,x);Cover(now<<1|1,a,b,x);
    pushup(now);
}
void Add(int now,int a,int b,int x){
    if(a>tree[now].r || b<tree[now].l) return;
    if(a<=tree[now].l && tree[now].r<=b){
        tree[now].add=+x;
        tree[now].mx+=x;return;
    }
    pushdown(now);
    Add(now<<1,a,b,x);Add(now<<1|1,a,b,x);
    pushup(now);
}
int query(int now,int a,int b){
    if(a>tree[now].r || b<tree[now].l) return 0;
    if(a<=tree[now].l && tree[now].r<=b) return tree[now].mx;
    pushdown(now);
    return max(query(now<<1,a,b),query(now<<1|1,a,b));
}
void PreCover(int x,int y,int c){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        //printf("*%d %d\n",w[top[x]],w[x]);
        Cover(1,w[top[x]],w[x],c);
        x=fa[f1];f1=top[x];
    }
    if(w[x]<w[y]){
        Cover(1,w[son[x]],w[y],c);
        //printf("*%d %d\n",w[son[x]],w[y]);
    }
    else if(w[x]>w[y]){
        Cover(1,w[son[y]],w[x],c);
        //printf("*%d %d\n",w[son[y]],w[x]);        
    }
}
void PreAdd(int x,int y,int c){
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        Add(1,w[top[x]],w[x],c);
        x=fa[f1];f1=top[x];
    }
    if(w[x]<w[y])
        Add(1,w[son[x]],w[y],c);
    else if(w[x]>w[y])
        Add(1,w[son[y]],w[x],c);
}
void PreMax(int x,int y){
    int ret=0;
    int f1=top[x],f2=top[y];
    while(f1!=f2){
        //printf("%d %d\n",x,y);
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        //printf("%d %d\n",w[top[x]],w[x]);
        ret=max(ret,query(1,w[top[x]],w[x]));
        x=fa[f1];f1=top[x];
    }
    if(w[x]<w[y]){
        ret=max(ret,query(1,w[son[x]],w[y]));
        //printf("%d %d\n",w[son[x]],w[y]);
    }
    else if(w[x]>w[y]){
        ret=max(ret,query(1,w[son[y]],w[x]));
        //printf("%d %d\n",w[son[y]],w[x]);
    }
    printf("%d\n",ret);
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    scanf("%d\n",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d%d\n",&bian[i].u,&bian[i].v,&bian[i].w);
        addedge(bian[i].u,bian[i].v,bian[i].w);addedge(bian[i].v,bian[i].u,bian[i].w);
    }
    dfs1(1,0);
    dfs2(1,1);
    for(int i=1;i<n;i++)
        if(bian[i].v==fa[bian[i].u])
            swap(bian[i].v,bian[i].u);
    //for(int i=1;i<=n;i++) printf("%d %d %d %d\n",i,w[i],son[i],top[i]);
    build(1,1,n);
    //for(int i=1;i<=4*n;i++) printf("%d %d %d\n",tree[i].l,tree[i].r,tree[i].mx);
    //Cover(1,9,13,2);Add(1,9,9,11);Add(1,1,4,1);printf("%d\n",query(1,2,9));
    //PreAdd(5,9,3);PreCover(3,9,1);PreAdd(3,9,6);PreMax(7,9);
    char s[10];
    while(scanf("%s",s) && s[0]!='S'){
        int x,y,c,i;
        if(s[1]=='a'){
            scanf("%d%d\n",&x,&y);
            PreMax(x,y);
        }
        if(s[1]=='h'){
            scanf("%d%d\n",&i,&x);
            Cover(1,w[bian[i].v],w[bian[i].v],x);
        }
        if(s[1]=='o'){
            scanf("%d%d%d\n",&x,&y,&c);
            PreCover(x,y,c);
        }
        if(s[1]=='d'){
            scanf("%d%d%d\n",&x,&y,&c);
            PreAdd(x,y,c);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值