bzoj3306: 树

xiaoxiao2021-02-27  314

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=3306

题解

  mdzz我把maxk写成了maxn,不TLE才怪呢,随机数据死活拍不出错。   看来以后做树的题目应该把链、菊花图、扫把图都造一遍。   可以自行 YY dfs 序+线段树。    popoqqq 大爷就是强,用了 stl+lct ,我虽然也能口胡但是绝对不敢写…

代码

//线段树+dfs序 #include <cstdio> #include <algorithm> #include <cmath> #define maxn 200010 #define maxk 18 using namespace std; int N, head[maxn], to[maxn], w[maxn], nex[maxn], tid[maxn], val[maxn], tmp[maxn], deep[maxn], R, tot, f[maxn][maxk], ndtot, Q, out[maxn]; struct segtree{int l, r, min;segtree *ch[2];}pool[maxn], *root; void segchg(segtree *p, int pos, int v) { int mid=p->l+p->r>>1; if(p->l==p->r){p->min=v;return;} if(pos<=mid)segchg(p->ch[0],pos,v); else segchg(p->ch[1],pos,v); p->min=min(p->ch[0]->min,p->ch[1]->min); } int segmin(segtree *p, int l, int r) { int mid=p->l+p->r>>1, ans=0x7fffffff; if(l<=p->l and r>=p->r)return p->min; if(l<=mid)ans=min(ans,segmin(p->ch[0],l,r)); if(r>mid)ans=min(ans,segmin(p->ch[1],l,r)); return ans; } void build(segtree *p, int l, int r) { int mid=l+r>>1; p->l=l, p->r=r; if(l==r){p->min=tmp[l];return;} build(p->ch[0]=pool+ ++ndtot,l,mid); build(p->ch[1]=pool+ ++ndtot,mid+1,r); p->min=min(p->ch[0]->min,p->ch[1]->min); } inline int read(int x=0) { char c=getchar(); while(c<48 or c>57)c=getchar(); while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar(); return x; } inline void adde(int a, int b){to[++tot]=b;nex[tot]=head[a];head[a]=tot;} void dfs(int pos, int pre) { int p; deep[pos]=deep[pre]+1; tid[pos]=++*tid; tmp[*tid]=val[pos]; for(p=head[pos];p;p=nex[p])dfs(to[p],pos); out[pos]=*tid; } void init() { int i, k; N=read(); Q=read(); for(i=1;i<=N;i++)f[i][0]=read(), val[i]=read(), adde(f[i][0],i); dfs(1,0); for(k=1;k<maxk;k++)for(i=1;i<=N;i++)f[i][k]=f[f[i][k-1]][k-1]; build(root=pool+ ++ndtot,1,N); } int lca(int x, int y) { int k; if(deep[x]>deep[y])swap(x,y); for(k=maxk-1;k>=0;k--)if(deep[f[y][k]]>=deep[x])y=f[y][k]; if(x==y)return x; for(k=maxk-1;k>=0;k--)if(f[x][k]^f[y][k])x=f[x][k],y=f[y][k]; return f[x][0]; } int quiry(int pos) { int tmp; int L, wh, ans=0x7fffffff, k; if(pos==R)return segmin(root,1,N); L=lca(R,pos); if(L!=pos)return segmin(root,tid[pos],out[pos]); wh=R; for(k=maxk-1;k>=0;k--)if(deep[f[wh][k]]>deep[pos])wh=f[wh][k]; ans=segmin(root,1,tid[wh]-1); if(out[wh]<N)ans=min(ans,segmin(root,out[wh]+1,N)); return ans; } int main() { char type[2]; int i, x, y; init(); for(i=1;i<=Q;i++) { scanf("%s",type); if(*type=='V') x=read(), y=read(), segchg(root,tid[x],y); else if(*type=='E')R=read(); else printf("%d\n",quiry(read())); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-2384.html

最新回复(0)