zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    UVA 408 (13.07.28)
    linux概念之用户,组及权限
    Java实现 蓝桥杯 历届试题 网络寻路
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 九宫重排
    Java实现 蓝桥杯 历届试题 九宫重排
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6760330.html
Copyright © 2011-2022 走看看