• AC日记——[国家集训队2011]旅游(宋方睿) cogs 1867


    [国家集训队2011]旅游(宋方睿)

    思路:

      树链剖分,边权转点权;

      线段树维护三个东西,sum,max,min;

      当一个区间变成相反数时,sum=-sum,max=-min,min=-max;

    来,上代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 100005
    #define ll long long
    #define INF 0x7fffffff
    
    struct TreeNodeType {
        ll l,r,mi,ma,sum,mid,flag;
    };
    struct TreeNodeType tree[maxn<<2];
    
    ll n,m,E[maxn<<1],V[maxn<<1],W[maxn<<1],cnt;
    ll deep[maxn],ps[maxn],pe[maxn],head[maxn],X,ty;
    ll f[maxn],id[maxn],ds[maxn],size[maxn],top[maxn];
    
    inline void in(ll &now)
    {
        ll if_z=1;now=0;
        char Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
    }
    
    inline void edge_add(ll u,ll v,ll w)
    {
        E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt;
        E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt;
    }
    
    void pre(ll now,ll fa)
    {
        f[now]=fa,size[now]=1;
        if(fa==-1) deep[now]=1;
        else deep[now]=deep[fa]+1;
        for(ll i=head[now];i;i=E[i])
        {
            if(V[i]==fa) continue;
            pre(V[i],now),size[now]+=size[V[i]];
        }
    }
    
    void dfs(ll now,ll chain,ll dis)
    {
        ll pos=n+1,ww;
        top[now]=chain,id[now]=++cnt,ds[cnt]=dis;
        for(ll i=head[now];i;i=E[i])
        {
            if(V[i]==f[now]) continue;
            if(size[V[i]]>size[pos]) pos=V[i],ww=W[i];
        }
        if(pos==n+1) return ;
        dfs(pos,chain,ww);
        for(ll i=head[now];i;i=E[i])
        {
            if(V[i]==pos||V[i]==f[now]) continue;
            dfs(V[i],V[i],W[i]);
        }
    }
    
    void tree_build(ll now,ll l,ll r)
    {
        tree[now].l=l,tree[now].r=r;
        if(l==r)
        {
            tree[now].mi=ds[l];
            tree[now].ma=ds[l];
            tree[now].sum=ds[l];
            return ;
        }
        tree[now].mid=l+r>>1;
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
        tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
        tree[now].ma=max(tree[now<<1].ma,tree[now<<1|1].ma);
        tree[now].mi=min(tree[now<<1].mi,tree[now<<1|1].mi);
    }
    
    inline void tree_down(ll now)
    {
        ll mii=tree[now<<1].mi,maa=tree[now<<1].ma;
        tree[now<<1].ma=-mii,tree[now<<1].mi=-maa;
        tree[now<<1].sum=-tree[now<<1].sum;
        mii=tree[now<<1|1].mi,maa=tree[now<<1|1].ma;
        tree[now<<1|1].mi=-maa,tree[now<<1|1].ma=-mii;
        tree[now<<1|1].sum=-tree[now<<1|1].sum;
        tree[now<<1].flag=!tree[now<<1].flag;
        tree[now<<1|1].flag=!tree[now<<1|1].flag;
        tree[now].flag=false;
    }
    
    void tree_query(ll now,ll l,ll r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            if(ty==1) X+=tree[now].sum;
            else if(ty==2) X=max(X,tree[now].ma);
            else X=min(X,tree[now].mi);
            return ;
        }
        if(tree[now].flag) tree_down(now);
        if(l>tree[now].mid) tree_query(now<<1|1,l,r);
        else if(r<=tree[now].mid) tree_query(now<<1,l,r);
        else tree_query(now<<1,l,tree[now].mid),tree_query(now<<1|1,tree[now].mid+1,r);
    }
    
    void tree_change(ll now,ll to)
    {
        if(tree[now].l==tree[now].r)
        {
            tree[now].mi=X;
            tree[now].ma=X;
            tree[now].sum=X;
            return ;
        }
        if(tree[now].flag) tree_down(now);
        if(to<=tree[now].mid) tree_change(now<<1,to);
        else tree_change(now<<1|1,to);
        tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
        tree[now].ma=max(tree[now<<1].ma,tree[now<<1|1].ma);
        tree[now].mi=min(tree[now<<1].mi,tree[now<<1|1].mi);
    }
    
    void tree_change_(ll now,ll l,ll r)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            tree[now].flag=!tree[now].flag;
            ll mii=tree[now].mi,maa=tree[now].ma;
            tree[now].sum=-tree[now].sum;
            tree[now].ma=-mii,tree[now].mi=-maa;
            return ;
        }
        if(tree[now].flag) tree_down(now);
        if(l>tree[now].mid) tree_change_(now<<1|1,l,r);
        else if(r<=tree[now].mid) tree_change_(now<<1,l,r);
        else tree_change_(now<<1,l,tree[now].mid),tree_change_(now<<1|1,tree[now].mid+1,r);
        tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
        tree[now].ma=max(tree[now<<1].ma,tree[now<<1|1].ma);
        tree[now].mi=min(tree[now<<1].mi,tree[now<<1|1].mi);
    }
    
    void solve_change(ll x,ll y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            tree_change_(1,id[top[x]],id[x]);
            x=f[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        if(x!=y) tree_change_(1,id[x]+1,id[y]);
    }
    
    void solve_query(ll x,ll y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            tree_query(1,id[top[x]],id[x]);
            x=f[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        if(x!=y) tree_query(1,id[x]+1,id[y]);
    }
    
    int main()
    {
        freopen("nt2011_travel.in","r",stdin);
        freopen("nt2011_travel.out","w",stdout);
        in(n);ll u,v,w;
        for(ll i=1;i<n;i++)
        {
            in(u),in(v),in(w);
            edge_add(u,v,w);
            ps[i]=u,pe[i]=v;
        }
        cnt=0,pre(0,-1),dfs(0,0,0);
        tree_build(1,1,n);
        in(m);char ch[10];
        while(m--)
        {
            scanf("%s",ch);in(u),in(v);
            if(ch[0]=='N') solve_change(u,v);
            else if(ch[0]=='C')
            {
                X=v;
                if(deep[ps[u]]>deep[pe[u]]) swap(ps[u],pe[u]);
                tree_change(1,id[pe[u]]);
            }
            else if(ch[0]=='S') ty=1,X=0,solve_query(u,v),printf("%lld
    ",X);
            else if(ch[0]=='M')
            {
                if(ch[1]=='A') ty=2,X=-INF,solve_query(u,v),printf("%lld
    ",X);
                else ty=3,X=INF,solve_query(u,v),printf("%lld
    ",X);
            }
        }
        fclose(stdin),fclose(stdout);
        return 0;
    }
  • 相关阅读:
    快速上手Unity原生Json库
    Unity3D安卓出包报错
    Git快速入门
    [Modern OpenGL系列(四)]在OpenGL中使用Shader
    [Modern OpenGL系列(三)]用OpenGL绘制一个三角形
    [Modern OpenGL系列(二)]创建OpenGL窗口
    [Modern OpenGL系列(一)]十步搞定OpenGL开发环境
    [Unity游戏开发]向量在游戏开发中的应用(三)
    [Unity游戏开发]向量在游戏开发中的应用(二)
    【leetcode】-两数之和
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6760330.html
Copyright © 2020-2023  润新知