P1505 [国家集训队] 旅游
P1505 [国家集训队] 旅游
题目背景
Ray 乐忠于旅游,这次他来到了 T 城。T 城是一个水上城市,一共有 \(n\) 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有 \(n-1\) 座桥。
Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度 \(w\),也就是说,Ray 经过这座桥会增加 \(w\) 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。
现在,Ray 想让你帮他计算从 \(u\) 景点到 \(v\) 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
题目描述
给定一棵 \(n\) 个节点的树,边带权,编号 \(0 \sim n-1\),需要支持五种操作:
C i w将输入的第 \(i\) 条边权值改为 \(w\);N u v将 \(u,v\) 节点之间的边权都变为相反数;SUM u v询问 \(u,v\) 节点之间边权和;MAX u v询问 \(u,v\) 节点之间边权最大值;MIN u v询问 \(u,v\) 节点之间边权最小值。
保证任意时刻所有边的权值都在 \([-1000,1000]\) 内。
输入格式
第一行一个正整数 \(n\),表示节点个数。
接下来 \(n-1\) 行,每行三个整数 \(u,v,w\),表示 \(u,v\) 之间有一条权值为 \(w\) 的边,描述这棵树。
然后一行一个正整数 \(m\),表示操作数。
接下来 \(m\) 行,每行表示一个操作。
输出格式
对于每一个询问操作,输出一行一个整数表示答案。
说明/提示
【数据范围】
对于 \(100\%\) 的数据,\(1\le n,m \le 2\times 10^5\)。
Solution:
一道十分经典的树链剖分练手题,我们将边权改点权(每个点对应其认父边的边长)
然后我们在线段树上维护一下 \(mn,mx,sum\) 就好了。
Code:
#include<bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
const int N=2e5+5;
const int inf=1e9;
using namespace std;
int head[N],dfn[N],siz[N],son[N],dis[N],top[N],dep[N],val[N];
int id[N],fa[N];
char c[50];
int e_cnt,n,m,dfn_cnt;
struct Edge{
int to,nxt,w;
}e[N<<1];
struct Tree{
int l,r,ma,mi,sum,tag;
}t[N<<2];
inline void pushup(int x)
{
t[x].mi=min(t[ls].mi,t[rs].mi);t[x].ma=max(t[ls].ma,t[rs].ma);
t[x].sum=t[ls].sum+t[rs].sum;
return ;
}
inline void build(int x,int l,int r)
{
t[x].tag=0;
t[x].l=l,t[x].r=r;
if(l==r)
{
t[x].mi=t[x].ma=t[x].sum=dis[id[l]];
return;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x);
}
inline void pushdown(int x)
{
if(!t[x].tag)return;
t[ls].mi=-t[ls].mi;t[rs].mi=-t[rs].mi;
t[ls].ma=-t[ls].ma;t[rs].ma=-t[rs].ma;
t[ls].sum=-t[ls].sum;t[rs].sum=-t[rs].sum;
t[ls].tag^=1;t[rs].tag^=1;
swap(t[ls].mi,t[ls].ma);swap(t[rs].mi,t[rs].ma);
t[x].tag=0;
return;
}
inline void upd_tag(int x,int ll,int rr,int tag)
{
if(ll<=t[x].l&&t[x].r<=rr)
{
t[x].tag^=tag;
t[x].ma=-t[x].ma;t[x].mi=-t[x].mi;t[x].sum=-t[x].sum;
swap(t[x].mi,t[x].ma);
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(ll<=mid)upd_tag(ls,ll,rr,tag);
if(rr>mid)upd_tag(rs,ll,rr,tag);
pushup(x);
}
inline void upd_val(int x,int pos,int val)
{
if(t[x].l==t[x].r)
{
t[x].mi=t[x].ma=t[x].sum=val;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(pos<=mid)upd_val(ls,pos,val);
else upd_val(rs,pos,val);
pushup(x);
}
inline void query(int x,int ll,int rr,Tree &res)
{
if(ll<=t[x].l&&t[x].r<=rr)
{
res.sum+=t[x].sum;res.ma=max(res.ma,t[x].ma);res.mi=min(res.mi,t[x].mi);
return ;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(ll<=mid)query(ls,ll,rr,res);
if(rr>mid)query(rs,ll,rr,res);
pushup(x);
}
inline void add(int x,int y,int w)
{
e[++e_cnt]=(Edge){y,head[x],w};
head[x]=e_cnt;
}
inline void dfs1(int x,int f)
{
fa[x]=f;siz[x]=1;dep[x]=dep[f]+1;
for(int i=head[x];i;i=e[i].nxt)
{
int to=e[i].to;
if(to==fa[x])continue;
dis[to]=e[i].w;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>siz[son[x]])son[x]=to;
}
}
inline void dfs2(int x,int tp)
{
top[x]=tp;dfn[x]=++dfn_cnt;id[dfn_cnt]=x;
if(!son[x])return;
dfs2(son[x],tp);
for(int i=head[x];i;i=e[i].nxt)
{
int to=e[i].to;
if(to==fa[x]||to==son[x])continue;
dfs2(to,to);
}
}
inline void chain_upd_tag(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
int tp=top[x];
upd_tag(1,dfn[tp],dfn[x],1);
x=fa[tp];
}
if(dep[x]<dep[y])swap(x,y);
if(x==y)return;
upd_tag(1,dfn[y]+1,dfn[x],1);
return ;
}
inline void chain_query(int x,int y,Tree &res)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
int tp=top[x];
query(1,dfn[tp],dfn[x],res);
x=fa[tp];
}
if(dep[x]<dep[y])swap(x,y);
if(x==y)return ;
query(1,dfn[y]+1,dfn[x],res);
}
inline void solve()
{
cin>>n;
for(int i=1,x,y,w;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x+1,y+1,w);add(y+1,x+1,w);
}
dfs1(1,0);dfs2(1,1);
build(1,1,n);
cin>>m;
int id=1;
for(int i=1,u,v;i<=m;i++)
{
scanf("%s",c);
scanf("%d%d",&u,&v);
if(c[0]=='C')
{
int uu=e[(u<<1)].to,vv=e[(u<<1)-1].to;
if(dep[uu]<dep[vv])swap(uu,vv);
upd_val(1,dfn[uu],v);
continue;
}
if(c[0]=='N')
{
chain_upd_tag(u+1,v+1);
continue;
}
Tree ans=(Tree){0,0,-inf,inf,0,0};
chain_query(u+1,v+1,ans);
if(c[1]=='U')
printf("%d\n",ans.sum);
if(c[1]=='A')
printf("%d\n",ans.ma);
if(c[1]=='I')
printf("%d\n",ans.mi);
}
}
#undef ls
#undef rs
int main()
{
// freopen("P1505_1.in","r",stdin);freopen("trip.out","w",stdout);
solve();
return 0;
}

浙公网安备 33010602011771号