BZOJ3306: 树

来源:互联网 发布:鼠标宏编程怎么使用 编辑:程序博客网 时间:2024/05/29 02:46

一开始随便找一个根建树
修改点权在dfs序上改
询问x的子树时,如果x是当前根p的父亲,设y为p的祖先中,x的孩子,那么x的子树就是整棵树除去y的子树范围,否则子树范围不变,在dfs序上找最小值

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline void read(int &x){    char c;    while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';}inline int _min(const int &x,const int &y){return x<y?x:y;}inline void swap(int &x,int &y){x^=y;y^=x;x^=y;}const int maxn = 110000;const int maxd = 21;int n,m,root;struct edge{    int y,nex;    edge(){}    edge(const int &_y,const int &_nex){y=_y;nex=_nex;}}a[maxn]; int len,fir[maxn];inline void ins(const int x,const int y){a[++len]=edge(y,fir[x]);fir[x]=len;}int siz[maxn],dep[maxn],fa[maxn][maxd];int id[maxn],dfn,idx[maxn];void dfs(const int x){    siz[x]=1; id[x]=++dfn; idx[dfn]=x;    for(int i=1;i<maxd;i++) fa[x][i]=fa[fa[x][i-1]][i-1];    for(int k=fir[x];k;k=a[k].nex)    {        const int y=a[k].y;        if(y!=fa[x][0])        {            fa[y][0]=x;            dep[y]=dep[x]+1;            dfs(y);            siz[x]+=siz[y];        }    }}int LCA(int x,int y,int &son){    if(dep[x]<dep[y]) swap(x,y);    for(int i=maxd-1;dep[x]!=dep[y]&&i>=0;i--)        if(dep[x]-dep[y]>1<<i) x=fa[x][i];    if(fa[x][0]==y) { son=x; return y; }    for(int i=maxd-1;i>=0;i--)        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];    son=x;    return fa[x][0];}int s[maxn];int seg[maxn<<2];void build_(const int x,const int l,const int r){    if(l==r) { seg[x]=s[idx[l]]; return ; }    int mid=l+r>>1,lc=x<<1,rc=lc|1;    build_(lc,l,mid); build_(rc,mid+1,r);    seg[x]=_min(seg[lc],seg[rc]);}int loc,c;void upd(const int x,const int l,const int r){    if(l==r) { seg[x]=c; return ; }    int mid=l+r>>1,lc=x<<1,rc=lc|1;    if(loc<=mid) upd(lc,l,mid);    else upd(rc,mid+1,r);    seg[x]=_min(seg[lc],seg[rc]);}int lx,rx;int query(const int x,const int l,const int r){    if(rx<l||r<lx) return INT_MAX;    if(lx<=l&&r<=rx) return seg[x];    int mid=l+r>>1,lc=x<<1,rc=lc|1;    return _min(query(lc,l,mid),query(rc,mid+1,r));}int main(){    read(n); read(m);    for(int i=1;i<=n;i++)    {        int fa,v; read(fa); read(v);        if(fa) ins(fa,i);        else root=i;        s[i]=v;    }    dep[root]=1; dfs(root);    build_(1,1,dfn);    char str[110];    for(int i=1;i<=m;i++)    {        scanf("%s",str);        if(str[0]=='V')        {            int x,y; read(x); read(y);            loc=id[x]; c=y; s[x]=y;            upd(1,1,dfn);            continue;        }        if(str[0]=='E')        {            int x; read(x);            root=x;             continue;        }        if(str[0]=='Q')        {            int x; read(x);            if(root==x) { printf("%d\n",seg[1]); continue; }            int f2,f1=LCA(root,x,f2);            if(f1==root||f1!=x)            {                lx=id[x],rx=lx+siz[x]-1;                printf("%d\n",query(1,1,dfn));                continue;            }            if(f1==x)            {                int ans=s[x];                lx=1,rx=id[f2]-1; if(lx<=rx) ans=_min(ans,query(1,1,dfn));                lx=id[f2]+siz[f2],rx=dfn; if(lx<=rx) ans=_min(ans,query(1,1,dfn));                printf("%d\n",ans);            }        }    }    return 0;}
0 0