Tree

题目

题目描述

在这里插入图片描述

输入格式

在这里插入图片描述

输出格式

在这里插入图片描述

样例

样例输入

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

样例输出

1
3

题解

SP375的变体,树链剖分好题一个lazy标志传递错误让我调了半天……
先把边权化为点权,建一张新图
对这张新图跑树链剖分,建一棵线段树来维护区间最大和最小值(正常是只需要最大值,但是因为要去相反数,所以需要维护最小值)
对于$3$个操作:

  1. 修改单边权:直接单点修改就可以了
  2. 路径取反:划分一下重链,直接区间修改,最大值和最小值取反后交换就好了
  3. 路径查询:划分重链,直接区间查询最大值

附上代码:

#include<iostream>
#include<cstdio>
using namespace std;
#define l(X) t[X].l
#define r(X) t[X].r
#define d(X) t[X].max
#define x(X) t[X].min
#define a(X) t[X].add
struct Segment_Tree
{
    int l,r,max,min,add;
}t[400010];
int n,tot,U[100010],V[100010],head[100010],to[200010],ver[200010],nxt[200010],big[100010];
int cnt,top[100010],dep[100010],siz[100010],dfn[100010],fa[100010],wei[100010],sor[100010],p[100010];
char op[10];
void add(int u,int v,int w)
{
    nxt[++tot]=head[u],head[u]=tot,to[tot]=v,ver[tot]=w;
}
void dfs1(int u,int Fa)
{
    fa[u]=Fa,dep[u]=dep[Fa]+1,siz[u]=1;
    for(int i=head[u];i;i=nxt[i]) if(to[i]!=Fa){
        wei[to[i]]=ver[i],dfs1(to[i],u),siz[u]+=siz[to[i]],p[(i-1)/2+1]=to[i];
        if((!big[u])||siz[to[i]]>siz[big[u]]) big[u]=to[i];
    }
}
void dfs2(int u,int Top)
{
    dfn[u]=++cnt,sor[cnt]=u,top[u]=Top;
    if(!big[u]) return;
    dfs2(big[u],Top);
    for(int i=head[u];i;i=nxt[i]) if(to[i]!=fa[u]&&to[i]!=big[u]) dfs2(to[i],to[i]);
}
void build(int p,int l,int r)
{
    l(p)=l,r(p)=r,d(p)=0x7fffffff,x(p)=-0x7fffffff,a(p)=0;
    if(l==r){d(p)=x(p)=wei[sor[l]];return;}
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    d(p)=max(d(p*2),d(p*2+1)),x(p)=min(x(p*2),x(p*2+1));
}
void spread(int p)
{
    if(a(p)){
        int temp,add=a(p);
        a(p)=0;
        if(!(add&1)) return;
        temp=d(p*2),d(p*2)=-x(p*2),x(p*2)=-temp,a(p*2)+=add;
        temp=d(p*2+1),d(p*2+1)=-x(p*2+1),x(p*2+1)=-temp,a(p*2+1)+=add;
    }
}
void change(int p,int x,int d)
{
    if(l(p)==r(p)){d(p)=x(p)=d;return;}
    spread(p);
    int mid=(l(p)+r(p))/2;
    if(x<=mid) change(p*2,x,d);
    else change(p*2+1,x,d);
    d(p)=max(d(p*2),d(p*2+1)),x(p)=min(x(p*2),x(p*2+1));
}
void Negate(int p,int l,int r)
{
    if(l(p)>=l&&r(p)<=r){int temp=d(p);d(p)=-x(p),x(p)=-temp,a(p)++;return;}
    spread(p);
    int mid=(l(p)+r(p))/2;
    if(l<=mid) Negate(p*2,l,r);
    if(r>mid) Negate(p*2+1,l,r);
    d(p)=max(d(p*2),d(p*2+1)),x(p)=min(x(p*2),x(p*2+1));
}
long long ask(int p,int l,int r)
{
    if(l(p)>=l&&r(p)<=r){return d(p);}
    spread(p);
    int mid=(l(p)+r(p))/2;
    long long ans=-0x7fffffff;
    if(l<=mid) ans=max(ans,ask(p*2,l,r));
    if(r>mid) ans=max(ans,ask(p*2+1,l,r));
    return ans;
}
int main()
{
    cin>>n;
    for(int i=1,u,v,w;i<n;i++) scanf("%d%d%d",&u,&v,&w),U[i]=u,V[i]=v,add(u,v,w),add(v,u,w);
    dfs1(1,0),dfs2(1,0);
    build(1,1,n);
    while(1){
        int a,b;
        cin>>op;
        if(op[0]=='D') break;
        scanf("%d%d",&a,&b);
        if(op[0]=='C') change(1,dfn[p[a]],b);
        if(op[0]=='N'){
            for(int ta=top[a],tb=top[b];ta!=tb;)
                if(dep[ta]>dep[tb]) Negate(1,dfn[ta],dfn[a]),a=fa[ta],ta=top[a];
                else Negate(1,dfn[tb],dfn[b]),b=fa[tb],tb=top[b];
            if(a==b) continue;
            if(dep[a]<dep[b]) Negate(1,dfn[big[a]],dfn[b]);
            else Negate(1,dfn[big[b]],dfn[a]);
        }
        if(op[0]=='Q'){ 
            long long ans=-0x7fffffff;
            for(int ta=top[a],tb=top[b];ta!=tb;)
                if(dep[ta]>dep[tb]) ans=max(ans,ask(1,dfn[ta],dfn[a])),a=fa[ta],ta=top[a];
                else ans=max(ans,ask(1,dfn[tb],dfn[b])),b=fa[tb],tb=top[b];
            if(a==b){printf("%lld\n",ans);continue;}
            if(dep[a]<dep[b]) ans=max(ans,ask(1,dfn[big[a]],dfn[b]));
            else ans=max(ans,ask(1,dfn[big[b]],dfn[a]));
            printf("%lld\n",ans);
        }
    }
}

喜欢的话,给博主赏一杯冰阔乐吧~


  转载请注明: Maserhe Tree

 上一篇
BZOJ4499 线性函数 BZOJ4499 线性函数
题目题目描述 小C最近在学习线性函数,线性函数可以表示为:$f(x) = kx + b$。现在小C面前有$n$个线性函数$f_i=k_ix+b_i$,他对这$n$个线性函数执行$m$次操作,每次可以: M i K B代表把第$i$个线性函
2020-03-27
下一篇 
W的火星工程 W的火星工程
题目题目描述 大老板W的伟大工程扩大到了火星,他准备在火星建立一个自己的度假村在他的度假村里,有两个大饭店A,B对于W来说,修建度假村必不可少的就是从A饭店向B饭店修路,以保证他可以短时间内享受各种美味火星上有一些中转站,中转站之间以及它们
2020-03-21
  目录