1. 程式人生 > >[國家集訓隊]旅遊

[國家集訓隊]旅遊

while dfs 之間 out pac 心情 可能 一個 每次

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\n",que(u,v,0)); else if(s[0]==M&&s[1]==A)printf("%d\n",que(u,v,1)); else printf("%d\n",que(u,v,2)); } return 0; }

[國家集訓隊]旅遊