BZOJ 3306 树
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3306 树相关的知识,希望对你有一定的参考价值。
dfs序建线段树+分类讨论+写的有点长。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 100500 #define maxe 200500 #define inf 2147483646 using namespace std; int n,m,w[maxv],dfn[maxv],fdfn[maxv],g[maxv],nume=0,x,y,cnt=0,dis[maxv],mx[maxv],anc[maxv][23]; int tot=0,root,ls[maxv<<2],rs[maxv<<2],val[maxv<<2],nrt; char s[4]; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void dfs(int x,int fath) { dfn[x]=++cnt;mx[x]=dfn[x];fdfn[cnt]=x; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (v==fath) continue; dis[v]=dis[x]+1; dfs(v,x);anc[v][0]=x; mx[x]=max(mx[x],mx[v]); } } void get_table() { for (int e=1;e<=20;e++) for (int i=1;i<=n;i++) anc[i][e]=anc[anc[i][e-1]][e-1]; } void build(int &now,int left,int right) { now=++tot; if (left==right) { val[now]=w[fdfn[left]]; return; } int mid=(left+right)>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); val[now]=min(val[ls[now]],val[rs[now]]); } void modify(int now,int left,int right,int pos) { if ((left==right) && (left==pos)) { val[now]=w[fdfn[left]]; return; } int mid=(left+right)>>1; if (pos<=mid) modify(ls[now],left,mid,pos); else modify(rs[now],mid+1,right,pos); val[now]=min(val[ls[now]],val[rs[now]]); } int ask(int now,int left,int right,int l,int r) { if (l>r) return inf; if ((l<=0) || (r>=n+1)) return inf; if ((left==l) && (right==r)) return val[now]; int mid=(left+right)>>1; if (r<=mid) return ask(ls[now],left,mid,l,r); else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r); else return min(ask(ls[now],left,mid,l,mid),ask(rs[now],mid+1,right,mid+1,r)); } int find(int x,int pos) { for (int e=20;e>=0;e--) { if (dis[anc[x][e]]>dis[pos]) x=anc[x][e]; } return x; } int main() { freopen("cin.in","r",stdin); freopen("a.out","w",stdout); nrt=1; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d%d",&x,&w[i]); if (x!=0) {addedge(i,x);addedge(x,i);} } dfs(1,1); get_table(); build(root,1,n); for (int i=1;i<=m;i++) { scanf("%s",s); if (s[0]==‘V‘) { scanf("%d%d",&x,&y); w[x]=y; modify(root,1,n,dfn[x]); } else if (s[0]==‘E‘) scanf("%d",&nrt); else { scanf("%d",&x); if (x==nrt) printf("%d\n",val[1]); else if ((dfn[nrt]>=dfn[x]) && (dfn[nrt]<=mx[x])) { int r=find(nrt,x); printf("%d\n",min(ask(root,1,n,1,dfn[r]-1),ask(root,1,n,mx[r]+1,n))); } else printf("%d\n",ask(root,1,n,dfn[x],mx[x])); } } return 0; }
以上是关于BZOJ 3306 树的主要内容,如果未能解决你的问题,请参考以下文章