[国家集训队]旅游
Posted zh-comld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[国家集训队]旅游相关的知识,希望对你有一定的参考价值。
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N ? 1 座桥。
Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。
现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
Solution
调了一下午+一晚上,唉,代码能力实在不行。
一眼链剖维护。
线段树记一个最大值,最小值,区间和。
犯的错:while写成if,单点修改时要把所有数据清空,标记下传时tag^=1,每次修改都要pushup。
Code
#include<iostream> #include<cstdio> #define N 200002 #define inf 0x7f7f7f7f using namespace std; int size[N],head[N],son[N],tot,topo,top[N],fa[N],num[N],dfn[N],deep[N],n,ji[N],m,jj[N]; char s[10]; int tr[N<<2],ma[N<<2],mi[N<<2]; bool la[N<<2]; struct ff{ int n,to,l,tag; }e[N<<1]; inline void add(int u,int v,int l,int tag){ e[++tot].n=head[u]; e[tot].to=v; head[u]=tot;e[tot].l=l;e[tot].tag=tag; } void dfs(int u,int f){ size[u]=1; for(int i=head[u];i;i=e[i].n)if(e[i].to!=f){ int v=e[i].to; deep[v]=deep[u]+1;fa[v]=u; dfs(v,u); size[u]+=size[v]; jj[e[i].tag]=v; num[v]=e[i].l; if(size[v]>size[son[u]])son[u]=v; } } void dfs2(int u){ dfn[u]=++topo; ji[topo]=u; if(!top[u])top[u]=u; if(son[u])top[son[u]]=top[u],dfs2(son[u]); for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa[u]&&e[i].to!=son[u])dfs2(e[i].to); } inline void pushdown(int cnt){ tr[cnt<<1]*=-1;tr[cnt<<1|1]*=-1; ma[cnt<<1]*=-1;ma[cnt<<1|1]*=-1; mi[cnt<<1]*=-1;mi[cnt<<1|1]*=-1; swap(ma[cnt<<1],mi[cnt<<1]);swap(ma[cnt<<1|1],mi[cnt<<1|1]); la[cnt]^=1;la[cnt<<1]^=1;la[cnt<<1|1]^=1; } void update2(int cnt,int l,int r,int L,int R){ if(l>=L&&r<=R){ tr[cnt]*=-1;mi[cnt]*=-1;ma[cnt]*=-1;la[cnt]^=1; swap(mi[cnt],ma[cnt]); return; } int mid=(l+r)>>1; if(la[cnt])pushdown(cnt); if(mid>=L)update2(cnt<<1,l,mid,L,R); if(mid<R) update2(cnt<<1|1,mid+1,r,L,R); tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1]; ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]); mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); } int query(int cnt,int l,int r,int L,int R,int tag){//0求和1最大值2最小值 if(l>=L&&r<=R){ if(!tag)return tr[cnt]; if(tag==1)return ma[cnt]; return mi[cnt]; } int mid=(l+r)>>1; if(la[cnt])pushdown(cnt); int ans=0,ans1=-inf,ans2=inf; if(mid>=L){ int bi=query(cnt<<1,l,mid,L,R,tag); if(tag==0)ans+=bi; else if(tag==1)ans1=max(ans1,bi); else ans2=min(ans2,bi); } if(mid<R){ int bi=query(cnt<<1|1,mid+1,r,L,R,tag); if(!tag)ans+=bi; else if(tag==1)ans1=max(ans1,bi); else ans2=min(ans2,bi); } // tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1]; // ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]); // mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); if(!tag)return ans; else if(tag==1)return ans1; else return ans2; } int que(int x,int y,int tag){ int ans=0,ans1=-inf,ans2=inf; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); if(!tag)ans+=query(1,2,topo,dfn[top[x]],dfn[x],tag); else if(tag==1)ans1=max(ans1,query(1,2,topo,dfn[top[x]],dfn[x],tag)); else ans2=min(ans2,query(1,2,topo,dfn[top[x]],dfn[x],tag)); x=fa[top[x]]; } if(dfn[x]>dfn[y])swap(x,y); if(x!=y){ if(!tag)ans+=query(1,2,topo,dfn[x]+1,dfn[y],tag); else if(tag==1)ans1=max(ans1,query(1,2,topo,dfn[x]+1,dfn[y],tag)); else ans2=min(ans2,query(1,2,topo,dfn[x]+1,dfn[y],tag)); } if(!tag)return ans; else if(tag==1)return ans1; else return ans2; } void update(int cnt,int l,int r,int x,int y){ if(l==r){ tr[cnt]=mi[cnt]=ma[cnt]=y;la[cnt]=0; return; } int mid=(l+r)>>1; if(la[cnt])pushdown(cnt); if(mid>=x)update(cnt<<1,l,mid,x,y); else update(cnt<<1|1,mid+1,r,x,y); tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1]; ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]); mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); } void work(int u,int v){ while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]])swap(u,v); update2(1,2,topo,dfn[top[u]],dfn[u]); u=fa[top[u]]; } if(dfn[u]>dfn[v])swap(u,v); if(u!=v)update2(1,2,topo,dfn[u]+1,dfn[v]); } void build(int cnt,int l,int r){ if(l==r){ tr[cnt]=ma[cnt]=mi[cnt]=num[ji[l]]; return; } int mid=(l+r)>>1; build(cnt<<1,l,mid);build(cnt<<1|1,mid+1,r); tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1]; ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]); mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); } int main(){ // freopen("pus.in","r",stdin); // freopen("233.out","w",stdout); scanf("%d",&n);int u,v,w; for(int i=1;i<n;++i){ scanf("%d%d%d",&u,&v,&w); u++;v++;add(u,v,w,i),add(v,u,w,i); } dfs(1,0);dfs2(1); build(1,2,topo); scanf("%d",&m); while(m--){ cin>>s;scanf("%d%d",&u,&v);++u,++v; if(s[0]==‘C‘){--u;--v;update(1,2,topo,dfn[jj[u]],v);} else if(s[0]==‘N‘)work(u,v); else if(s[0]==‘S‘)printf("%d ",que(u,v,0)); else if(s[0]==‘M‘&&s[1]==‘A‘)printf("%d ",que(u,v,1)); else printf("%d ",que(u,v,2)); } return 0; }
以上是关于[国家集训队]旅游的主要内容,如果未能解决你的问题,请参考以下文章