P6157 有趣的游戏
P6157 有趣的游戏
题意简述:
给你一棵树,要求你维护一条链上任意两点
Solution:
我们不难发现,在一些数中最大的
所以我们只需要建一颗线段树来维护区间前四大值
Code:
#include<bits/stdc++.h> const int N=1e5+5; using namespace std; int n,m; int w[N]; struct Tree{ int l,r; int val[5],cnt[5]; }; struct Segment_Tree{ #define ls x<<1 #define rs x<<1|1 Tree t[N<<2]; void clear(Tree &T) { for(int i=0;i<4;i++){T.val[i]=T.cnt[i]=0;} } void pushup(Tree &T,Tree L,Tree R) { int i=0,j=0,k=0; while(k<4) { if(L.val[i]==R.val[j]) { T.val[k]=L.val[i]; T.cnt[k]=L.cnt[i]+R.cnt[j]; i++,j++,k++; } if(L.val[i]>R.val[j]&&k<4) { T.val[k]=L.val[i]; T.cnt[k]=L.cnt[i]; i++,k++; } if(L.val[i]<R.val[j]&&k<4) { T.val[k]=R.val[j]; T.cnt[k]=R.cnt[j]; j++,k++; } } } void build(int x,int l,int r) { t[x].l=l,t[x].r=r; if(l==r){t[x].val[0]=w[l];t[x].cnt[0]=1;return ;} int mid=l+r>>1; build(ls,l,mid);build(rs,mid+1,r); pushup(t[x],t[ls],t[rs]); } void upd(int x,int pos,int k) { if(t[x].l==t[x].r){clear(t[x]);t[x].val[0]=k;t[x].cnt[0]=1;return ;} int mid=t[x].l+t[x].r>>1; if(pos<=mid)upd(ls,pos,k); if(mid<pos) upd(rs,pos,k); pushup(t[x],t[ls],t[rs]); } void query(int x,int L,int R,Tree &res) { if(L<=t[x].l&&t[x].r<=R) { pushup(res,res,t[x]); return ; } int mid=t[x].l+t[x].r>>1; if(L<=mid)query(ls,L,R,res); if(mid<R) query(rs,L,R,res); } #undef ls #undef rs }T; struct Graph{ int head[N]; struct Edge{ int to,nxt; }e[N<<1]; void add(int x,int y) { e[++head[0]]=Edge{y,head[x]}; head[x]=head[0]; } int fa[N],top[N],dep[N],dfn[N],rid[N],val[N]; int son[N],siz[N]; void dfs1(int x,int ff) { dep[x]=dep[ff]+1;fa[x]=ff; siz[x]=1; for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(y==fa[x])continue; dfs1(y,x); siz[x]+=siz[y]; son[x] = siz[y] > siz[son[x]] ? y : son[x]; } } void dfs2(int x,int tp) { dfn[x]=++dfn[0];rid[dfn[0]]=x; top[x]=tp; w[dfn[0]]=val[x]; if(!son[x])return ; dfs2(son[x],tp); for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(y==fa[x]||y==son[x])continue; dfs2(y,y); } } Tree chain_query(int x,int y) { Tree res={0,0,{0},{0}}; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); T.query(1,dfn[top[x]],dfn[x],res); x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y); T.query(1,dfn[y],dfn[x],res); return res; } }G; void work() { cin>>n; for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); G.add(x,y);G.add(y,x); } for(int i=1;i<=n;i++) { scanf("%d",&G.val[i]); } G.dfs1(1,0); G.dfs2(1,1); T.build(1,1,n); cin>>m; for(int i=1;i<=m;i++) { int opt,x,y; scanf("%d%d%d",&opt,&x,&y); if(opt==0) { w[G.dfn[x]]+=y; T.upd(1,G.dfn[x],w[G.dfn[x]]); } if(opt==1) { Tree A=G.chain_query(x,y); Tree B={0,0,{0},{0}}; T.query(1,1,n,B); if(!A.val[1]){printf("%d\n",-1);continue;} int ans_A=A.val[1],ans_B=0; for(int j=0;j<2;j++)for(int k=0;k<4;k++)if(A.val[j]==B.val[k])B.cnt[k]--; for(int k=0,tag=0;k<4;k++){if(tag&&B.cnt[k]>0){ans_B=B.val[k];break;}if(B.cnt[k]>0)tag=1;} printf("%d %d\n",ans_A,ans_B); } } } int main() { //freopen("P6157.in","r",stdin);freopen("P6157.out","w",stdout); work(); return 0; }