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;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6760330.html