zoukankan      html  css  js  c++  java
  • 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
    ", Query_sum(x,y));
            } else if(s[0]=='M'){
                if(s[1]=='I'){
                    printf("%d
    ", Query_mn(x,y));
                } else printf("%d
    ", Query_mx(x,y));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    nginx超时问题
    linux打包文件,压缩文件
    centos查看文件夹大小
    Nginx反向代理和负载均衡
    nginx的location配置详解
    nginx错误Upstream timed out
    mysql处理函数
    SQL左右连接中的on and和on where的区别
    html select change事件触发
    get,post区别
  • 原文地址:https://www.cnblogs.com/victorique/p/10247011.html
Copyright © 2011-2022 走看看