cogs||bzoj1036 树的统计count
题目大意:模板题。
思路:模板题。
#include<iostream> #include<cstdio> #define maxnode 30001 #define mid (l+r)/2 #define inf 2100000000LL using namespace std; struct use{ int fa,top,siz,son,dep,tid; }tree[maxnode]={0}; struct seg{ int maxn,sum; }t[maxnode*4]={0}; int point[maxnode*2]={0},next[maxnode*2]={0},en[maxnode*2],tot=0,tt[maxnode],wi[maxnode]; char ch[10]; bool visit[maxnode]={false}; void add(int st,int enn) { ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn; ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st; } void findc(int u,int fa,int depth) { int i,j,maxsiz=0; visit[u]=true;tree[u].siz=1; tree[u].fa=fa;tree[u].dep=depth; for (i=point[u];i;i=next[i]) if (!visit[en[i]]) { j=en[i];findc(j,u,depth+1); tree[u].siz+=tree[j].siz; if (tree[j].siz>maxsiz) { maxsiz=tree[j].siz; tree[u].son=j; } } } void connc(int u,int top) { int i,j; visit[u]=false;tree[u].top=top; tree[u].tid=++tot;tt[tot]=u; if (tree[u].son) connc(tree[u].son,top); for (i=point[u];i;i=next[i]) if (visit[en[i]]) { j=en[i];connc(j,j); } } void updata(int i) { t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn); t[i].sum=t[i*2].sum+t[i*2+1].sum; } void build(int i,int l,int r) { if (l==r) { t[i].maxn=t[i].sum=wi[tt[l]];return; } build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i); } void change(int i,int l,int r,int x,int y) { if (l==r) { t[i].maxn=t[i].sum=y;return; } if (x<=mid) change(i*2,l,mid,x,y); else change(i*2+1,mid+1,r,x,y); updata(i); } int tmax(int i,int l,int r,int ll,int rr) { int maxn; if (ll<=l&&r<=rr) return t[i].maxn; maxn=-inf; if (ll<=mid) maxn=max(maxn,tmax(i*2,l,mid,ll,rr)); if (rr>mid) maxn=max(maxn,tmax(i*2+1,mid+1,r,ll,rr)); return maxn; } int tsum(int i,int l,int r,int ll,int rr) { int sum=0; if (ll<=l&&r<=rr) return t[i].sum; if (ll<=mid) sum+=tsum(i*2,l,mid,ll,rr); if (rr>mid) sum+=tsum(i*2+1,mid+1,r,ll,rr); return sum; } int qmax(int x,int y) { int maxn; maxn=-inf; while(tree[x].top!=tree[y].top) { if (tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); maxn=max(maxn,tmax(1,1,tot,tree[tree[x].top].tid,tree[x].tid)); x=tree[tree[x].top].fa; } if (tree[x].dep<tree[y].dep) swap(x,y); maxn=max(maxn,tmax(1,1,tot,tree[y].tid,tree[x].tid)); return maxn; } int qsum(int x,int y) { int sum=0; while(tree[x].top!=tree[y].top) { if (tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y); sum+=tsum(1,1,tot,tree[tree[x].top].tid,tree[x].tid); x=tree[tree[x].top].fa; } if (tree[x].dep<tree[y].dep) swap(x,y); sum+=tsum(1,1,tot,tree[y].tid,tree[x].tid); return sum; } int main() { freopen("bzoj_1036.in","r",stdin); freopen("bzoj_1036.out","w",stdout); int i,j,n,m,a,b,ans; scanf("%d",&n); for (i=1;i<n;++i) { scanf("%d%d",&a,&b); add(a,b); } findc(1,0,1); tot=0;connc(1,1); for (i=1;i<=n;++i) scanf("%d",&wi[i]); build(1,1,tot); scanf("%d",&m); for (i=1;i<=m;++i) { scanf("%*c%s",&ch);scanf("%d%d",&a,&b); if (ch[0]=='C') change(1,1,tot,tree[a].tid,b); else { if (ch[1]=='M') ans=qmax(a,b); else ans=qsum(a,b); printf("%d\n",ans); } } fclose(stdin); fclose(stdout); }
cogs 树的维护
题目大意:模板题+区间取反。
思路:取反的时候是纯线段树操作,有很多细节:insert、updata和ask的时候都要考虑delta的取值。
#include<iostream> #include<cstdio> #include<cstring> #define maxnode 10001 #define mid (l+r)/2 #define inf 2100000000 using namespace std; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2],va[maxnode*2],bi[maxnode*2],tt[maxnode]={0},wi[maxnode]; char ch[10]; struct use{ int maxn,minn,delta,sig; }t[maxnode*4]; void updata(int i) { t[i].maxn=max((t[i].sig==t[i*2].sig ? t[i*2].maxn : -t[i*2].minn),(t[i].sig==t[i*2+1].sig ? t[i*2+1].maxn : -t[i*2+1].minn)); t[i].minn=min((t[i].sig==t[i*2].sig ? t[i*2].minn : -t[i*2].maxn),(t[i].sig==t[i*2+1].sig ? t[i*2+1].minn : -t[i*2+1].maxn)); } void build(int i,int l,int r) { if (l==r) { t[i].maxn=t[i].minn=wi[tt[l]]; t[i].delta=t[i].sig=0;return; } build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i); } void paint(int i) { t[i].sig=1-t[i].sig;t[i].delta=1-t[i].delta; } void pushdown(int i) { if (t[i].delta) { paint(i*2);paint(i*2+1); t[i].delta=0; } } void tchange(int i,int l,int r,int x,int y) { if (l==r) { if (t[i].sig) t[i].maxn=t[i].minn=-y; else t[i].maxn=t[i].minn=y; return; } pushdown(i); if (x<=mid) tchange(i*2,l,mid,x,y); else tchange(i*2+1,mid+1,r,x,y); updata(i); } void tneg(int i,int l,int r,int ll,int rr) { if (ll<=l&&r<=rr) { paint(i);return; } pushdown(i); if (ll<=mid) tneg(i*2,l,mid,ll,rr); if (rr>mid) tneg(i*2+1,mid+1,r,ll,rr); updata(i); } int tmax(int i,int l,int r,int ll,int rr) { int maxn; if (ll<=l&&r<=rr) { if (t[i].sig) return -t[i].minn; else return t[i].maxn; } maxn=-inf;pushdown(i); if (ll<=mid) maxn=max(maxn,tmax(i*2,l,mid,ll,rr)); if (rr>mid) maxn=max(maxn,tmax(i*2+1,mid+1,r,ll,rr)); return maxn; } struct lp{ int fa[maxnode],son[maxnode],dep[maxnode],top[maxnode],siz[maxnode],tid[maxnode],edge[maxnode],tot; bool visit[maxnode]; void add(int st,int enn,int vaa,int i) { ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn;va[tot]=vaa;bi[tot]=i; ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st;va[tot]=vaa;bi[tot]=i; } void dfs1(int u,int ff,int depth,int vaa,int ii) { int i,j,maxsiz=0; visit[u]=true;fa[u]=ff;dep[u]=depth; son[u]=0;siz[u]=1;wi[u]=vaa;edge[ii]=u; for (i=point[u];i;i=next[i]) if (!visit[j=en[i]]) { dfs1(j,u,depth+1,va[i],bi[i]); siz[u]+=siz[j]; if (siz[j]>maxsiz) { maxsiz=siz[j];son[u]=j; } } } void dfs2(int u,int anc) { int i,j; visit[u]=false;top[u]=anc; tid[u]=++tot;tt[tot]=u; if (son[u]) dfs2(son[u],anc); for (i=point[u];i;i=next[i]) if (visit[j=en[i]]) dfs2(j,j); } void change(int a,int b) { a=tid[edge[a]]; tchange(1,1,tot,a,b); } void neg(int a,int b) { while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) swap(a,b); tneg(1,1,tot,tid[top[a]],tid[a]); a=fa[top[a]]; } if (dep[a]>dep[b]) swap(a,b); if (a!=b) tneg(1,1,tot,tid[son[a]],tid[b]); } void qmax(int a,int b) { int maxn; maxn=-inf; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) swap(a,b); maxn=max(maxn,tmax(1,1,tot,tid[top[a]],tid[a])); a=fa[top[a]]; } if (dep[a]>dep[b]) swap(a,b); if (a!=b) maxn=max(maxn,tmax(1,1,tot,tid[son[a]],tid[b])); printf("%d\n",maxn); } }tree; int main() { freopen("maintaintree.in","r",stdin); freopen("maintaintree.out","w",stdout); int n,i,j,a,b,c; scanf("%d",&n);tree.tot=0; memset(tree.visit,false,sizeof(tree.visit)); for (i=1;i<n;++i) { scanf("%d%d%d",&a,&b,&c); tree.add(a,b,c,i); } tree.dfs1(1,0,1,0,0); tree.tot=0;tree.dfs2(1,1); build(1,1,tree.tot); while(scanf("%*c%s",&ch)==1) { if (ch[0]=='D') break; scanf("%d%d",&a,&b); if (ch[0]=='C') tree.change(a,b); if (ch[0]=='N') tree.neg(a,b); if (ch[0]=='Q') tree.qmax(a,b); } fclose(stdin); fclose(stdout); }
bzoj3083 遥远的国度
题目大意:换父亲、改点权、子树最小值。
思路:换父亲是三种情况的分类讨论:我们并不是真的换父亲、重新建树。当前根root,子树的根节点x。1)如果root=x,就查询整棵树;2)如果当lca(root,x)!=x,就查询x的子树;3)如果当lca(root,x)=x,就查询x的儿子中离root最近的那个儿子在整棵树中的补集。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxnode 100001 #define inf 0x7fffffff using namespace std; struct use{ int delta,minn; }t[maxnode*4]={0}; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},tot=0,id[maxnode]={0}; void updata(int i) { t[i].minn=min(t[i*2].minn,t[i*2+1].minn); } void pushdown(int i) { if (t[i].delta) { t[i*2].minn=t[i*2].delta=t[i].delta; t[i*2+1].minn=t[i*2+1].delta=t[i].delta; t[i].delta=0; } } void build(int i,int l,int r) { int mid; if (l==r) { t[i].delta=0;t[i].minn=fy[id[l]];return; } mid=(l+r)/2; build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i); } void tch(int i,int l,int r,int ll,int rr,int v) { int mid; if (ll<=l&&r<=rr) { t[i].delta=t[i].minn=v;return; } mid=(l+r)/2; pushdown(i); if (ll<=mid) tch(i*2,l,mid,ll,rr,v); if (rr>mid) tch(i*2+1,mid+1,r,ll,rr,v); updata(i); } int task(int i,int l,int r,int ll,int rr) { int mid,ans; if (ll<=l&&r<=rr) return t[i].minn; mid=(l+r)/2;ans=inf;pushdown(i); if (ll<=mid) ans=min(ans,task(i*2,l,mid,ll,rr)); if (rr>mid) ans=min(ans,task(i*2+1,mid+1,r,ll,rr)); return ans; } struct lp{ int fa[maxnode][20],son[maxnode],dep[maxnode],top[maxnode],siz[maxnode],tid[maxnode],ri[maxnode]; bool visit[maxnode]; void add(int st,int enn) { ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn; ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st; } void dfs1(int u,int ff,int depth) { int i,j,maxsiz=0; visit[u]=true;fa[u][0]=ff;dep[u]=depth; son[u]=0;siz[u]=1; for (i=1;i<=18;++i) fa[u][i]=fa[fa[u][i-1]][i-1]; for (i=point[u];i;i=next[i]) { if (!visit[j=en[i]]) { dfs1(j,u,depth+1); siz[u]+=siz[j]; if (siz[j]>maxsiz) { maxsiz=siz[j];son[u]=j; } } } } void dfs2(int u,int anc) { int i,j; visit[u]=false;top[u]=anc; tid[u]=++tot;id[tot]=u; if (son[u]) dfs2(son[u],anc); for (i=point[u];i;i=next[i]) { if (visit[j=en[i]]) dfs2(j,j); } ri[u]=tot; } int lca(int a,int b) { int i,j; if (dep[a]>dep[b]) swap(a,b); for (i=18;i>=0;--i) if (dep[a]<=dep[fa[b][i]]) b=fa[b][i]; if (a==b) return a; for (i=18;i>=0;--i) { if (fa[a][i]!=fa[b][i]) { a=fa[a][i];b=fa[b][i]; } } return fa[a][0]; } void change(int a,int b,int v) { int i,j; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) swap(a,b); tch(1,1,tot,tid[top[a]],tid[a],v); a=fa[top[a]][0]; } if (dep[a]>dep[b]) swap(a,b); tch(1,1,tot,tid[a],tid[b],v); } int ask(int a,int root) { int ans,ll,i,j; if (a==root) return task(1,1,tot,1,tot); ll=lca(a,root); if (ll!=a) return task(1,1,tot,tid[a],ri[a]); else { ans=inf;j=root; for (i=18;i>=0;--i) if (dep[fa[j][i]]>dep[a]) j=fa[j][i]; ans=min((tid[j]>1 ? task(1,1,tot,1,tid[j]-1) : inf),(ri[j]<tot ? task(1,1,tot,ri[j]+1,tot) : inf)); return ans; } } }tree; int main() { int u,v,n,m,i,j,opt,root,p1,p2,ans; scanf("%d%d",&n,&m); for (i=1;i<n;++i) { scanf("%d%d",&u,&v); tree.add(u,v); } for (i=1;i<=n;++i) scanf("%d",&fy[i]); scanf("%d",&root);tot=0; memset(tree.visit,false,sizeof(tree.visit)); tree.dfs1(root,0,1); tree.dfs2(root,root); build(1,1,tot); for (i=1;i<=m;++i) { scanf("%d",&opt); if (opt==1) scanf("%d",&root); if (opt==2) { scanf("%d%d%d",&p1,&p2,&v); tree.change(p1,p2,v); } if (opt==3) { scanf("%d",&p1); ans=tree.ask(p1,root); printf("%d\n",ans); } } }
bzoj2243 染色
题目大意:区间修改、区间不同子段的个数。
思路:线段树上的操作。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxnode 100001 using namespace std; struct use{ int lc,rc,sum,delta; }t[maxnode*4]={0}; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},id[maxnode]={0},tot=0,fy[maxnode]={0}; void updata(int i) { t[i].lc=t[i*2].lc;t[i].rc=t[i*2+1].rc; t[i].sum=t[i*2].sum+t[i*2+1].sum; if (t[i*2].rc==t[i*2+1].lc) --t[i].sum; } void pushdown(int i) { if (t[i].delta>=0) { t[i*2].lc=t[i*2].rc=t[i*2].delta=t[i].delta;t[i*2].sum=1; t[i*2+1].lc=t[i*2+1].rc=t[i*2+1].delta=t[i].delta;t[i*2+1].sum=1; t[i].delta=-1; } } void build(int i,int l,int r) { int mid; if (l==r) { t[i].lc=t[i].rc=fy[id[l]];t[i].sum=1;t[i].delta=-1;return; } mid=(l+r)/2; build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i);t[i].delta=-1; } void tch(int i,int l,int r,int ll,int rr,int v) { int mid; if (ll<=l&&r<=rr) { t[i].lc=t[i].rc=t[i].delta=v;t[i].sum=1;return; } mid=(l+r)/2;pushdown(i); if (ll<=mid) tch(i*2,l,mid,ll,rr,v); if (rr>mid) tch(i*2+1,mid+1,r,ll,rr,v); updata(i); } struct use task(int i,int l,int r,int ll,int rr) { int mid,sum=0; bool u1=false,u2=false; struct use n1,n2,ans; if (ll<=l&&r<=rr) return t[i]; mid=(l+r)/2;pushdown(i); if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);} if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);} if (u1) ans.lc=n1.lc; else ans.lc=n2.lc; if (u2) ans.rc=n2.rc; else ans.rc=n1.rc; ans.sum=(u1 ? n1.sum : 0)+(u2 ? n2.sum : 0); if (u1&&u2&&n1.rc==n2.lc) --ans.sum; return ans; } struct lp{ int fa[maxnode],dep[maxnode],son[maxnode],siz[maxnode],top[maxnode],tid[maxnode]; bool visit[maxnode]; void add(int u,int v) { ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u; } void dfs1(int u,int ff,int depth) { int i,j,maxsiz=0; fa[u]=ff;dep[u]=depth;son[u]=0; visit[u]=true;siz[u]=1; for (i=point[u];i;i=next[i]) { if (!visit[j=en[i]]) { dfs1(j,u,depth+1); siz[u]+=siz[j]; if (siz[j]>maxsiz) { maxsiz=siz[j];son[u]=j; } } } } void dfs2(int u,int anc) { int i,j; tid[u]=++tot;top[u]=anc; visit[u]=false;id[tot]=u; if (son[u]) dfs2(son[u],anc); for (i=point[u];i;i=next[i]) { if (visit[j=en[i]]) dfs2(j,j); } } void change(int a,int b,int v) { int i; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) swap(a,b); tch(1,1,tot,tid[top[a]],tid[a],v); a=fa[top[a]]; } if (dep[a]>dep[b]) swap(a,b); tch(1,1,tot,tid[a],tid[b],v); } int ask(int a,int b) { int ans=0,co[2],kk=0; struct use i; co[0]=co[1]=-1; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[top[a]],tid[a]); ans+=i.sum; if (co[kk]==i.rc) --ans; co[kk]=i.lc; a=fa[top[a]]; } if (dep[a]>dep[b]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[a],tid[b]); ans+=i.sum; if (co[kk]==i.lc) --ans; co[kk]=i.rc; if (co[kk]==co[kk^1]) --ans; return ans; } }tree; int main() { int n,m,i,j,u,v,t; char ch; scanf("%d%d",&n,&m); for (i=1;i<=n;++i) scanf("%d",&fy[i]); for (i=1;i<n;++i) { scanf("%d%d",&u,&v);tree.add(u,v); } memset(tree.visit,false,sizeof(tree.visit)); tree.dfs1(1,0,1);tot=0; tree.dfs2(1,1);build(1,1,tot); for (i=1;i<=m;++i) { while(scanf("%c",&ch)==1) { if (ch=='C'||ch=='Q') break; } if (ch=='C') { scanf("%d%d%d",&u,&v,&t); tree.change(u,v,t); } else { scanf("%d%d",&u,&v); printf("%d\n",tree.ask(u,v)); } } }
codevs3305&&3306 水果姐逛水果街系列
题目大意:查询树上从a到b的路径中后面减前面的最大差值(+单点修改)。
思路:链剖+线段树的操作,稍复杂一点,分类讨论。有点像上一题。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxnode 200001 #define inf 2100000000 using namespace std; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},id[maxnode]={0},tot=0; struct use{ int maxn,minn,mac,mic; }t[maxnode*4]; void updata(int i) { t[i].mac=max(t[i*2].mac,max(t[i*2+1].mac,t[i*2+1].maxn-t[i*2].minn)); t[i].mic=max(t[i*2].mic,max(t[i*2+1].mic,t[i*2].maxn-t[i*2+1].minn)); t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn); t[i].minn=min(t[i*2].minn,t[i*2+1].minn); } void build(int i,int l,int r) { int mid; if (l==r) { t[i].maxn=t[i].minn=fy[id[l]];t[i].mac=t[i].mic=0;return; } mid=(l+r)/2; build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i); } void tch(int i,int l,int r,int x,int y) { int mid; if (l==r) { t[i].maxn=t[i].minn=y;t[i].mac=t[i].mic=0;return; } mid=(l+r)/2; if (x<=mid) tch(i*2,l,mid,x,y); else tch(i*2+1,mid+1,r,x,y); updata(i); } struct use task(int i,int l,int r,int ll,int rr) { int mid; struct use n1,n2,ans; bool u1=false,u2=false; if (ll<=l&&r<=rr) return t[i]; mid=(l+r)/2; if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);} if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);} ans.maxn=0;ans.minn=inf;ans.mac=ans.mic=0; if (u1) { ans.maxn=max(ans.maxn,n1.maxn); ans.minn=min(ans.minn,n1.minn); ans.mac=max(ans.mac,n1.mac); ans.mic=max(ans.mic,n1.mic); } if (u2) { ans.maxn=max(ans.maxn,n2.maxn); ans.minn=min(ans.minn,n2.minn); ans.mac=max(ans.mac,n2.mac); ans.mic=max(ans.mic,n2.mic); } if (u1&&u2) { ans.mac=max(ans.mac,n2.maxn-n1.minn); ans.mic=max(ans.mic,n1.maxn-n2.minn); } return ans; } struct lp{ int fa[maxnode],dep[maxnode],top[maxnode],tid[maxnode],son[maxnode],siz[maxnode]; bool visit[maxnode]; void add(int u,int v) { ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u; } void dfs1(int u,int ff,int depth) { int i,j,maxsiz=0; fa[u]=ff;dep[u]=depth;visit[u]=true; son[u]=0;siz[u]=1; for (i=point[u];i;i=next[i]) { if (!visit[j=en[i]]) { dfs1(j,u,depth+1); siz[u]+=siz[j]; if (siz[j]>maxsiz) { maxsiz=siz[j];son[u]=j; } } } } void dfs2(int u,int anc) { int i,j; top[u]=anc;tid[u]=++tot; id[tot]=u;visit[u]=false; if (son[u]) dfs2(son[u],anc); for (i=point[u];i;i=next[i]) if (visit[j=en[i]]) dfs2(j,j); } int ask(int a,int b) { int j,ans=0,kk=0; struct use mo[2],i; mo[0].maxn=mo[1].maxn=0;mo[0].minn=mo[1].minn=inf; mo[0].mac=mo[1].mac=mo[0].mic=mo[1].mic=0; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[top[a]],tid[a]); if (!kk) { ans=max(ans,max(i.mic,i.maxn-mo[kk].minn)); mo[kk].minn=min(mo[kk].minn,i.minn); mo[kk].maxn=max(mo[kk].maxn,i.maxn); } else { ans=max(ans,max(i.mac,mo[kk].maxn-i.minn)); mo[kk].minn=min(mo[kk].minn,i.minn); mo[kk].maxn=max(mo[kk].maxn,i.maxn); } a=fa[top[a]]; } if (dep[a]>dep[b]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[a],tid[b]); if (!kk) { ans=max(ans,max(i.mac,i.maxn-mo[kk].minn)); mo[kk].maxn=max(mo[kk].maxn,i.maxn); mo[kk].minn=min(mo[kk].minn,i.minn); ans=max(ans,mo[kk^1].maxn-mo[kk].minn); } else { ans=max(ans,max(i.mic,mo[kk].maxn-i.minn)); mo[kk].maxn=max(mo[kk].maxn,i.maxn); mo[kk].minn=min(mo[kk].minn,i.minn); ans=max(ans,mo[kk].maxn-mo[kk^1].minn); } return ans; } }tree; int main() { int n,m,i,j,x,y,u,v; scanf("%d",&n); for (i=1;i<=n;++i) scanf("%d",&fy[i]); for (i=1;i<n;++i) { scanf("%d%d",&u,&v); tree.add(u,v); } memset(tree.visit,false,sizeof(tree.visit)); tree.dfs1(1,0,1);tot=0; tree.dfs2(1,1);scanf("%d",&m); build(1,1,tot); for (i=1;i<=m;++i) { scanf("%d%d",&x,&y); printf("%d\n",tree.ask(x,y)); } }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxnode 200001 #define inf 2100000000 using namespace std; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},id[maxnode]={0},tot=0; struct use{ int maxn,minn,mac,mic; }t[maxnode*4]; void updata(int i) { t[i].mac=max(t[i*2].mac,max(t[i*2+1].mac,t[i*2+1].maxn-t[i*2].minn)); t[i].mic=max(t[i*2].mic,max(t[i*2+1].mic,t[i*2].maxn-t[i*2+1].minn)); t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn); t[i].minn=min(t[i*2].minn,t[i*2+1].minn); } void build(int i,int l,int r) { int mid; if (l==r) { t[i].maxn=t[i].minn=fy[id[l]];t[i].mac=t[i].mic=0;return; } mid=(l+r)/2; build(i*2,l,mid);build(i*2+1,mid+1,r); updata(i); } void tch(int i,int l,int r,int x,int y) { int mid; if (l==r) { t[i].maxn=t[i].minn=y;t[i].mac=t[i].mic=0;return; } mid=(l+r)/2; if (x<=mid) tch(i*2,l,mid,x,y); else tch(i*2+1,mid+1,r,x,y); updata(i); } struct use task(int i,int l,int r,int ll,int rr) { int mid; struct use n1,n2,ans; bool u1=false,u2=false; if (ll<=l&&r<=rr) return t[i]; mid=(l+r)/2; if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);} if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);} ans.maxn=0;ans.minn=inf;ans.mac=ans.mic=0; if (u1) { ans.maxn=max(ans.maxn,n1.maxn); ans.minn=min(ans.minn,n1.minn); ans.mac=max(ans.mac,n1.mac); ans.mic=max(ans.mic,n1.mic); } if (u2) { ans.maxn=max(ans.maxn,n2.maxn); ans.minn=min(ans.minn,n2.minn); ans.mac=max(ans.mac,n2.mac); ans.mic=max(ans.mic,n2.mic); } if (u1&&u2) { ans.mac=max(ans.mac,n2.maxn-n1.minn); ans.mic=max(ans.mic,n1.maxn-n2.minn); } return ans; } struct lp{ int fa[maxnode],dep[maxnode],top[maxnode],tid[maxnode],son[maxnode],siz[maxnode]; bool visit[maxnode]; void add(int u,int v) { ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u; } void dfs1(int u,int ff,int depth) { int i,j,maxsiz=0; fa[u]=ff;dep[u]=depth;visit[u]=true; son[u]=0;siz[u]=1; for (i=point[u];i;i=next[i]) { if (!visit[j=en[i]]) { dfs1(j,u,depth+1); siz[u]+=siz[j]; if (siz[j]>maxsiz) { maxsiz=siz[j];son[u]=j; } } } } void dfs2(int u,int anc) { int i,j; top[u]=anc;tid[u]=++tot; id[tot]=u;visit[u]=false; if (son[u]) dfs2(son[u],anc); for (i=point[u];i;i=next[i]) if (visit[j=en[i]]) dfs2(j,j); } int ask(int a,int b) { int j,ans=0,kk=0; struct use mo[2],i; mo[0].maxn=mo[1].maxn=0;mo[0].minn=mo[1].minn=inf; mo[0].mac=mo[1].mac=mo[0].mic=mo[1].mic=0; while(top[a]!=top[b]) { if (dep[top[a]]<dep[top[b]]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[top[a]],tid[a]); if (!kk) { ans=max(ans,max(i.mic,i.maxn-mo[kk].minn)); mo[kk].minn=min(mo[kk].minn,i.minn); mo[kk].maxn=max(mo[kk].maxn,i.maxn); } else { ans=max(ans,max(i.mac,mo[kk].maxn-i.minn)); mo[kk].minn=min(mo[kk].minn,i.minn); mo[kk].maxn=max(mo[kk].maxn,i.maxn); } a=fa[top[a]]; } if (dep[a]>dep[b]) { swap(a,b);kk^=1; } i=task(1,1,tot,tid[a],tid[b]); if (!kk) { ans=max(ans,max(i.mac,i.maxn-mo[kk].minn)); mo[kk].maxn=max(mo[kk].maxn,i.maxn); mo[kk].minn=min(mo[kk].minn,i.minn); ans=max(ans,mo[kk^1].maxn-mo[kk].minn); } else { ans=max(ans,max(i.mic,mo[kk].maxn-i.minn)); mo[kk].maxn=max(mo[kk].maxn,i.maxn); mo[kk].minn=min(mo[kk].minn,i.minn); ans=max(ans,mo[kk].maxn-mo[kk^1].minn); } return ans; } }tree; int main() { int n,m,i,j,x,y,u,v; scanf("%d",&n); for (i=1;i<=n;++i) scanf("%d",&fy[i]); for (i=1;i<n;++i) { scanf("%d%d",&u,&v); tree.add(u,v); } memset(tree.visit,false,sizeof(tree.visit)); tree.dfs1(1,0,1);tot=0; tree.dfs2(1,1);scanf("%d",&m); build(1,1,tot); for (i=1;i<=m;++i) { scanf("%d%d%d",&j,&x,&y); if (j==0) tch(1,1,tot,tree.tid[x],y); else printf("%d\n",tree.ask(x,y)); } }