BZOJ2157 旅游

BZOJ2157 旅游


题目描述

传送门

题目分析

给出一棵树,然后要求维护链边权和,链上最大最小值,以及链乘\(-1\)

考虑使用树链剖分,先把边权转化为父节点点权,然后直接维护就可以了。问题主要在于最小最大值在下传标记时的更改。显而易见的是这俩数都取反之后直接\(swap\)就可以了。

注意,根据线段树写法不同要在树剖里特判\(x=y\)的情况。

可笑的是这个题对于取相反数操作直接暴力递归到叶子节点也有极其优秀的表现。数据还真是。。。甚至某些错误写法也可通过。。。这。。。

是代码呢

#include <bits/stdc++.h>
using namespace std;
#define ls ((rt<<1))
#define rs ((rt<<1)|1)
#define mid ((l+r)>>1)
#define ll long long
const int MAXN=1e5+7;
const int inf=1e9+7;
int f[MAXN],id[MAXN],w[MAXN],at[MAXN],top[MAXN],dep[MAXN],wson[MAXN],size[MAXN],val[MAXN],cnt,n,m;
int mx[MAXN<<2],mn[MAXN<<2],rev[MAXN<<2],head[MAXN],num;
ll sum[MAXN<<2];
char s[5];
struct po{
    int nxt,to,dis,id;
}edge[MAXN];
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
inline void add_edge(int from,int to,int dis,int id)
{
    edge[++num].nxt=head[from];edge[num].to=to;edge[num].dis=dis;edge[num].id=id;head[from]=num;
    edge[++num].nxt=head[to];edge[num].to=from;edge[num].dis=dis;edge[num].id=id;head[to]=num;
}
inline void dfs(int u,int fa)
{
    size[u]=1;f[u]=fa;dep[u]=dep[fa]+1;
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==fa) continue;
        dfs(v,u);
        val[v]=edge[i].dis;
        at[edge[i].id]=v;
        size[u]+=size[v];
        if(size[wson[u]]<size[v]) wson[u]=v;
    }
}
inline void dfs2(int u,int tp)
{
    id[u]=++cnt;top[u]=tp;w[cnt]=val[u];
    if(wson[u]) dfs2(wson[u],tp);
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==f[u]||v==wson[u]) continue;
        dfs2(v,v);
    }
}
inline void pushup(int rt)
{
    sum[rt]=sum[ls]+sum[rs];
    mx[rt]=max(mx[ls],mx[rs]);
    mn[rt]=min(mn[ls],mn[rs]);
}
inline void build(int l,int r,int rt)
{
    rev[rt]=1;
    if(l==r){
        sum[rt]=mx[rt]=mn[rt]=w[l];
        return;
    }
    build(l,mid,ls);build(mid+1,r,rs);
    pushup(rt);
}
inline void pushdown(int l,int r,int rt)
{
    if(rev[rt]!=1){
        rev[ls]*=-1;rev[rs]*=-1;
        sum[ls]=-sum[ls]; sum[rs]=-sum[rs];
        int t=mx[ls];mx[ls]=-mn[ls];mn[ls]=-t;
        t=mx[rs];mx[rs]=-mx[rs];mn[rs]=-t;
        rev[rt]=1;
    }
}
inline void change(int x,int k,int l,int r,int rt)
{
    if(l==r){
        sum[rt]=mx[rt]=mn[rt]=k;
        return;
    }
    pushdown(l,r,rt);
    if(x<=mid) change(x,k,l,mid,ls);
    else change(x,k,mid+1,r,rs);
    pushup(rt);
}
//inline void update(int L,int R,int l,int r,int rt)
//{
//  if(L<=l&&r<=R){
//      sum[rt]=-sum[rt];
//      int t=mx[rt];
//      mx[rt]=-mn[rt];
//      mn[rt]=-t;
//      rev[rt]*=-1;
//      return;
//  }
//  pushdown(l,r,rt);
//  if(L<=mid) update(L,R,l,mid,ls);
//  if(R>mid) update(L,R,mid+1,r,rs);
//  pushup(rt);
//}
inline void update(int L,int R,int l,int r,int rt)
{
    if(r<L||l>R) return;
    if(l==r){
        sum[rt]*=-1;
        mx[rt]*=-1;
        mn[rt]*=-1;
        return;
    }
    update(L,R,l,mid,ls);update(L,R,mid+1,r,rs);
    pushup(rt);
}
inline ll query_sum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return sum[rt];
    ll ans=0;
    pushdown(l,r,rt);
    if(L<=mid) ans+=query_sum(L,R,l,mid,ls);
    if(R>mid) ans+=query_sum(L,R,mid+1,r,rs);
    return ans;
}
inline int query_mx(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return mx[rt];
    pushdown(l,r,rt);
    int maxx=-inf;
    if(L<=mid) maxx=max(maxx,query_mx(L,R,l,mid,ls));
    if(R>mid) maxx=max(maxx,query_mx(L,R,mid+1,r,rs));
    return maxx;
}
inline int query_mn(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return mn[rt];
    pushdown(l,r,rt);
    int minn=inf;
    if(L<=mid) minn=min(minn,query_mn(L,R,l,mid,ls));
    if(R>mid) minn=min(minn,query_mn(L,R,mid+1,r,rs));
    return minn;
}
inline void Update(int x,int y)
{
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        update(id[top[x]],id[x],1,n,1);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    update(id[x]+1,id[y],1,n,1);
}
inline ll Query_sum(int x,int y)
{
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=query_sum(id[top[x]],id[x],1,n,1);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=query_sum(id[x]+1,id[y],1,n,1);
    return ans;
}
inline int Query_mx(int x,int y)
{
    int ans=-inf;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=max(ans,query_mx(id[top[x]],id[x],1,n,1));
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=max(ans,query_mx(id[x]+1,id[y],1,n,1));
    return ans;
}
inline int Query_mn(int x,int y)
{
    int ans=inf;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=min(ans,query_mn(id[top[x]],id[x],1,n,1));
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=min(ans,query_mn(id[x]+1,id[y],1,n,1));
    return ans;
}
int main()
{
//  freopen("data.in","r",stdin);
//  freopen("my.out","w",stdout);
    n=read();
    for(int i=1;i<n;i++){
        int x=read()+1,y=read()+1,l=read();
        add_edge(x,y,l,i);
    }
    dfs(1,0);dfs2(1,1);build(1,n,1);
    m=read();
    while(m--){
        scanf("%s",s);
        int x=read()+1,y=read()+1;
        if(s[0]=='C'){
            x--;y--;
            change(id[at[x]],y,1,n,1);
        } else if(s[0]=='N'){
            Update(x,y);
        } else if(s[0]=='S'){
            printf("%lld\n", Query_sum(x,y));
        } else if(s[0]=='M'){
            if(s[1]=='I'){
                printf("%d\n", Query_mn(x,y));
            } else printf("%d\n", Query_mx(x,y));
        }
    }
    return 0;
}
posted @ 2019-01-09 21:39  ~victorique~  阅读(80)  评论(0编辑  收藏  举报
Live2D