bzoj3306: 树

来源:互联网 发布:ubuntu 开机自启动命令 编辑:程序博客网 时间:2024/06/08 10:57

链接

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

题解

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

代码

//线段树+dfs序#include <cstdio>#include <algorithm>#include <cmath>#define maxn 200010#define maxk 18using 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;}
0 0
原创粉丝点击