zoukankan      html  css  js  c++  java
  • P1505 [国家集训队]旅游

    题目大意:给定一棵树,你有5种操作:1、改变其中一条边的权值,2、将节点u到节点v的所有边权取反,3、求节点u到节点v路径所有边权之和,4、求节点u到节点v路径所有边权最大值,5、求节点u到节点v路径所有边权最小值。

    思路:一看题目这么长就知道码量不少qwq,这是一道裸的树链剖分,但有些细节要注意:首先是取反操作,取反后区间最大值变成区间最小值的相反数,区间最小值同理;还有就是树链剖分是解决点权的,边权怎么办呢?只要把边权变成他儿子的点权即可,其他都能用线段树解决,不过说起来简单,写起来嘛……(我才不会告诉你我写了1小时,调了1小时qwq

    代码如下:压行大法吼啊

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int MaxN=300000;
    struct edge{
        int to,next,w;
    }e[MaxN*2];
    struct tree{
        int lb,rb,sum,nmax,nmin,rev;
    }tr[MaxN*2];
    int n,m,a[MaxN],last[MaxN],tot;
    int id,dis[MaxN],fa[MaxN],son[MaxN],bel[MaxN],siz[MaxN],dfn[MaxN],top[MaxN];
    inline int read() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    void add_edge(int x,int y,int w){
        e[++tot].to=y;e[tot].next=last[x];e[tot].w=w;last[x]=tot;
        return;
    }
    void dfs1(int x,int f){
        dis[x]=dis[f]+1;siz[x]=1;fa[x]=f;int nmax=-0x3f3f3f3f;
        for(int i=last[x];i;i=e[i].next){
            int u=e[i].to;
            if(u==f) continue;
            dfs1(u,x);siz[x]+=siz[u];a[u]=e[i].w;
            if(siz[u]>nmax) nmax=siz[u],son[x]=u;
        }
        return;
    }
    void dfs2(int x,int rt){
        dfn[x]=++id;top[x]=rt;bel[id]=x;
        if(!son[x]) return;dfs2(son[x],rt);
        for(int i=last[x];i;i=e[i].next){
            int u=e[i].to;
            if(u==fa[x]||u==son[x]) continue;
            dfs2(u,u);
        }
        return;
    }
    void las(int x){
        tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
        tr[x].nmax=max(tr[x<<1].nmax,tr[x<<1|1].nmax);
        tr[x].nmin=min(tr[x<<1].nmin,tr[x<<1|1].nmin);
        return;
    }
    void build(int now,int l,int r){
        tr[now].lb=l;tr[now].rb=r;
        if(l==r){tr[now].sum=tr[now].nmax=tr[now].nmin=a[bel[l]];return;}
        int mid=(l+r)>>1;
        build(now<<1,l,mid);build(now<<1|1,mid+1,r);las(now);
        return;
    }
    void downlag(int x){
        if(tr[x].rev){
            swap(tr[x<<1].nmax,tr[x<<1].nmin);tr[x<<1].nmax*=-1;tr[x<<1].nmin*=-1;
            swap(tr[x<<1|1].nmax,tr[x<<1|1].nmin);tr[x<<1|1].nmax*=-1;tr[x<<1|1].nmin*=-1;
            tr[x<<1].sum*=-1;tr[x<<1|1].sum*=-1;
            tr[x<<1].rev^=1;tr[x<<1|1].rev^=1;tr[x].rev^=1;
        }
        return;
    }
    void chng(int now,int x,int w){
        if(tr[now].lb==x&&tr[now].rb==x){tr[now].sum=w;tr[now].nmax=w;tr[now].nmin=w;return;}
        downlag(now);//!
        int mid=(tr[now].lb+tr[now].rb)>>1;
        if(mid>=x) chng(now<<1,x,w);if(mid<x) chng(now<<1|1,x,w);
        las(now);return;
    }
    void invert(int now,int l,int r){
        if(tr[now].lb>=l&&tr[now].rb<=r){tr[now].sum*=-1;tr[now].rev^=1;swap(tr[now].nmax,tr[now].nmin);tr[now].nmax*=-1;tr[now].nmin*=-1;return;}
        downlag(now);
        int mid=(tr[now].lb+tr[now].rb)>>1;
        if(mid>=l) invert(now<<1,l,r);if(mid<r) invert(now<<1|1,l,r);
        las(now);return;
    }
    int query(int now,int l,int r){
        if(tr[now].lb>=l&&tr[now].rb<=r) return tr[now].sum;
        downlag(now);
        int mid=(tr[now].lb+tr[now].rb)>>1,ans=0;
        if(mid>=l) ans+=query(now<<1,l,r);if(mid<r) ans+=query(now<<1|1,l,r);
        return ans;
    }
    int Qmax(int now,int l,int r){
        if(tr[now].lb>=l&&tr[now].rb<=r) return tr[now].nmax;
        downlag(now);
        int mid=(tr[now].lb+tr[now].rb)>>1,ans=-0x3f3f3f3f;
        if(mid>=l) ans=max(ans,Qmax(now<<1,l,r));if(mid<r) ans=max(ans,Qmax(now<<1|1,l,r));
        return ans;
    }
    int Qmin(int now,int l,int r){
        if(tr[now].lb>=l&&tr[now].rb<=r) return tr[now].nmin;
        downlag(now);
        int mid=(tr[now].lb+tr[now].rb)>>1,ans=0x3f3f3f3f;
        if(mid>=l) ans=min(ans,Qmin(now<<1,l,r));if(mid<r) ans=min(ans,Qmin(now<<1|1,l,r));//Qmin->Qmax
        return ans;
    }
    void wvert(int x,int y){
        while(top[x]!=top[y]){
            if(dis[top[x]]<dis[top[y]]) swap(x,y);
            invert(1,dfn[top[x]],dfn[x]);x=fa[top[x]];
        }
        if(dis[x]<dis[y]) swap(x,y);
        if(y==x) return;invert(1,dfn[y]+1,dfn[x]);
        return;
    }
    int wmax(int x,int y){
        int ans=-0x3f3f3f3f;
        while(top[x]!=top[y]){
            if(dis[top[x]]<dis[top[y]]) swap(x,y);
            ans=max(ans,Qmax(1,dfn[top[x]],dfn[x]));x=fa[top[x]];
        }
        if(dis[x]<dis[y]) swap(x,y);
        if(x==y) return ans;ans=max(ans,Qmax(1,dfn[y]+1,dfn[x]));return ans;
    } 
    int wmin(int x,int y){
        int ans=0x3f3f3f3f;
        while(top[x]!=top[y]){
            if(dis[top[x]]<dis[top[y]]) swap(x,y);
            ans=min(ans,Qmin(1,dfn[top[x]],dfn[x]));x=fa[top[x]];
        }
        if(dis[x]<dis[y]) swap(x,y);
        if(x==y) return ans;ans=min(ans,Qmin(1,dfn[y]+1,dfn[x]));return ans;
    }
    int wsum(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(dis[top[x]]<dis[top[y]]) swap(x,y);
            ans+=query(1,dfn[top[x]],dfn[x]);x=fa[top[x]];
        }
        if(dis[x]<dis[y]) swap(x,y);
        if(x==y) return ans;ans+=query(1,dfn[y]+1,dfn[x]);return ans;
    }
    int main(){
        int x,y,w;char c[10];
        n=read();
        for(int i=1;i<n;++i){
            x=read();y=read();w=read();++x;++y;
            add_edge(x,y,w);add_edge(y,x,w);
        }
        m=read();dfs1(1,0);dfs2(1,1);build(1,1,n);
        while(m--){
            scanf("%s",c);x=read();y=read();
            if(c[0]=='S') printf("%d
    ",wsum(x+1,y+1));
            if(c[1]=='A') printf("%d
    ",wmax(x+1,y+1));
            if(c[1]=='I') printf("%d
    ",wmin(x+1,y+1));
            if(c[0]=='N') wvert(x+1,y+1);
            if(c[0]=='C') chng(1,dfn[x+1],y);
        }
        return 0;
    }
  • 相关阅读:
    hdoj 5311 Hidden String(KMP)
    hdoj 1532 Drainage Ditches(最大网络流)
    ubuntu中php+mysql环境搭建
    android:clipToPadding 和 android:clipChildren
    Js实现动画框架
    JavaScript初步认识
    JavaScript鼠标进入与退出监听动画
    Android框架集合
    Android 6.0(Android M)动态授权
    Android应用申请ROOT权限
  • 原文地址:https://www.cnblogs.com/X-rice/p/11219016.html
Copyright © 2011-2022 走看看