BZOJ-2157: 旅游

[文章目录]

Description

给你一颗n个节点带有边权的树,给出m次操作。1.更改一条边的边权。2.两点之间路径上的边的边权变为相反数。3.查询两点路径上的边中边权最大,最小值。4.查询两点路径上边权和。
n<=20000,m<=20000

树链剖分。取相反数相当于直接将维护的mx[],mi[],取相反数再swap,sum直接变成相反数。
和毛景树一样,边权转化到点上,lca不查。
压了一下行,哈哈哈

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 201000
using namespace std;
int n,m; char st[30];
int head[N],to[N<<1],nxt[N<<1],data[N<<1],id[N<<1],cnt;
void add(int x,int y,int z,int zz){to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; data[cnt]=z; id[cnt]=zz;}
int fa[N],siz[N],top[N],tid[N],tot,son[N],deep[N],w1[N],w2[N],atv[N];
void dfs1(int x)
{
    deep[x]=deep[fa[x]]+1; siz[x]++; int y,tmp=0;
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=fa[x])
        {
            fa[y=to[i]]=x; atv[id[i]]=y; w1[y]=data[i];
            dfs1(y); siz[x]+=siz[y];
            if(siz[y]>tmp) tmp=siz[y],son[x]=y;
        }
}
void dfs2(int x,int anc)
{
    tid[x]=++tot; top[x]=anc; w2[tot]=w1[x];
    if(son[x]) dfs2(son[x],anc);
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=son[x]&&to[i]!=fa[x])
            dfs2(to[i],to[i]);
}
bool la[N<<2];
int sum[N<<2],mx[N<<2],mi[N<<2];
void pushup(int pos)
{
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
    mx[pos]=max(mx[pos<<1],mx[pos<<1|1]);
    mi[pos]=min(mi[pos<<1],mi[pos<<1|1]);
}
void pushdown(int pos)
{
    if(!la[pos]) return ;
    sum[pos<<1]*=-1; swap(mi[pos<<1],mx[pos<<1]); mx[pos<<1]*=-1; mi[pos<<1]*=-1; la[pos<<1]^=1;
    sum[pos<<1|1]*=-1; swap(mi[pos<<1|1],mx[pos<<1|1]); mx[pos<<1|1]*=-1; mi[pos<<1|1]*=-1; la[pos<<1|1]^=1;
    la[pos]=0;
}
void build(int pos,int l,int r)
{
    if(l==r) {sum[pos]=mx[pos]=mi[pos]=w2[l]; return;}
    int mid=l+r>>1; build(pos<<1,l,mid); build(pos<<1|1,mid+1,r);
    pushup(pos);
}
void fix_v(int pos,int l,int r,int x,int y)
{
    if(l==r){mx[pos]=mi[pos]=sum[pos]=y; return;}
    int mid=l+r>>1; pushdown(pos);
    if(x<=mid) fix_v(pos<<1,l,mid,x,y);
    else fix_v(pos<<1|1,mid+1,r,x,y);
    pushup(pos);
}
void fix_e(int pos,int l,int r,int x,int y)
{
    if(x<=l&&y>=r) {sum[pos]*=-1; swap(mx[pos],mi[pos]); mx[pos]*=-1; mi[pos]*=-1; la[pos]^=1; return ;}
    int mid=l+r>>1; pushdown(pos);
    if(y<=mid) fix_e(pos<<1,l,mid,x,y);
    else if(x>mid) fix_e(pos<<1|1,mid+1,r,x,y);
    else fix_e(pos<<1,l,mid,x,y),fix_e(pos<<1|1,mid+1,r,x,y);
    pushup(pos);
}
int q_sum(int pos,int l,int r,int x,int y)
{
    if(x<=l&&y>=r) return sum[pos];
    int mid=l+r>>1,re; pushdown(pos);
    if(y<=mid) re=q_sum(pos<<1,l,mid,x,y);
    else if(x>mid) re=q_sum(pos<<1|1,mid+1,r,x,y);
    else re=q_sum(pos<<1,l,mid,x,y)+q_sum(pos<<1|1,mid+1,r,x,y);
    pushup(pos); return re;
}
int q_max(int pos,int l,int r,int x,int y)
{
    if(x<=l&&y>=r) return mx[pos];
    int mid=l+r>>1,re; pushdown(pos);
    if(y<=mid) re=q_max(pos<<1,l,mid,x,y);
    else if(x>mid) re=q_max(pos<<1|1,mid+1,r,x,y);
    else re=max(q_max(pos<<1,l,mid,x,y),q_max(pos<<1|1,mid+1,r,x,y));
     pushup(pos); return re;
}
int q_min(int pos,int l,int r,int x,int y)
{
    if(x<=l&&y>=r) return mi[pos];
    int mid=l+r>>1,re; pushdown(pos);
    if(y<=mid) re=q_min(pos<<1,l,mid,x,y);
    else if(x>mid) re=q_min(pos<<1|1,mid+1,r,x,y);
    else re=min(q_min(pos<<1,l,mid,x,y),q_min(pos<<1|1,mid+1,r,x,y));
    pushup(pos); return re;
}
void Fix_v()
{
    int x,y; scanf("%d%d",&x,&y);
    fix_v(1,1,n,tid[atv[x]],y);
}
void Fix_e()
{
    int x,y; scanf("%d%d",&x,&y); x++,y++;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        fix_e(1,1,n,tid[top[x]],tid[x]); x=fa[top[x]];
    }
    if(x==y) return ;
    if(deep[x]>deep[y]) swap(x,y);
    fix_e(1,1,n,tid[x]+1,tid[y]);
}
void Q_sum()
{
    int ans=0,x,y; scanf("%d%d",&x,&y); x++,y++;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans+=q_sum(1,1,n,tid[top[x]],tid[x]); x=fa[top[x]];
    }
    if(x==y){printf("%d\n",ans); return ;}
    if(deep[x]>deep[y]) swap(x,y);
    ans+=q_sum(1,1,n,tid[x]+1,tid[y]);
    printf("%d\n",ans); return ;
}
void Q_max()
{
    int ans=-1<<30,x,y; scanf("%d%d",&x,&y); x++,y++;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans=max(ans,q_max(1,1,n,tid[top[x]],tid[x])); x=fa[top[x]];
    }
    if(x==y){printf("%d\n",ans); return ;}
    if(deep[x]>deep[y]) swap(x,y);
    ans=max(ans,q_max(1,1,n,tid[x]+1,tid[y]));
    printf("%d\n",ans); return ;
}
void Q_min()
{
    int ans=1<<30,x,y; scanf("%d%d",&x,&y); x++,y++;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans=min(ans,q_min(1,1,n,tid[top[x]],tid[x])); x=fa[top[x]];
    }
    if(x==y){printf("%d\n",ans); return ;}
    if(deep[x]>deep[y]) swap(x,y);
    ans=min(ans,q_min(1,1,n,tid[x]+1,tid[y]));
    printf("%d\n",ans); return ;
}
int main()
{
    scanf("%d",&n); int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z); x++,y++;
        add(x,y,z,i); add(y,x,z,i);
    }
    dfs1(1); dfs2(1,1); build(1,1,n);
    scanf("%d",&m);
    while(m--)
    {
        scanf("%s",st);
        if(st[0]=='C') Fix_v();
        else if(st[0]=='N') Fix_e();
        else if(st[0]=='S') Q_sum();
        else if(st[1]=='A') Q_max();
        else Q_min();
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注