首页 > 技术文章 > [HEOI2016/TJOI2016]树

skylee03 2018-03-30 14:20 原文

题目大意:
  给定一棵$n(n\le10^5)$个结点的以$1$为根的树,初始时$1$为标记结点。有$m(m\le10^5)$次操作,操作包含以下两种:
    1.将点$x$打上标记;
    2.询问点$x$到根路径上离$x$最近的标记点。

思路:
  树链剖分线段树单点修改,区间询问DFS序最大标记点。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<algorithm>
  4 inline int getint() {
  5     register char ch;
  6     while(!isdigit(ch=getchar()));
  7     register int x=ch^'0';
  8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  9     return x; 
 10 }
 11 inline char getalpha() {
 12     register char ch;
 13     while(!isalpha(ch=getchar()));
 14     return ch;
 15 }
 16 const int N=1e5+1;
 17 int h[N],size[N],son[N],dfn[N],id[N],par[N],top[N],sz;
 18 struct Edge {
 19     int to,next;
 20 };
 21 Edge e[N<<1];
 22 inline void add_edge(const int &u,const int &v) {
 23     e[++sz]=(Edge){v,h[u]};h[u]=sz;
 24 }
 25 void dfs1(const int &x,const int &par) {
 26     size[x]=1;
 27     ::par[x]=par;
 28     for(int i=h[x];i;i=e[i].next) {
 29         const int &y=e[i].to;
 30         if(y==par) continue;
 31         dfs1(y,x);
 32         size[x]+=size[y];
 33         if(size[y]>size[son[x]]) son[x]=y;
 34     }
 35 }
 36 void dfs2(const int &x) {
 37     id[dfn[x]=++dfn[0]]=x;
 38     top[x]=x==son[par[x]]?top[par[x]]:x;
 39     if(son[x]) dfs2(son[x]);
 40     for(int i=h[x];i;i=e[i].next) {
 41         const int &y=e[i].to;
 42         if(y==par[x]||y==son[x]) continue;
 43         dfs2(y);
 44     }
 45 }
 46 class SegmentTree {
 47     #define _left <<1
 48     #define _right <<1|1
 49     #define _par >>1
 50     private:
 51         int val[N<<2];
 52         void push_up(const int &p) {
 53             val[p]=std::max(val[p _left],val[p _right]);
 54         }
 55     public:
 56         void modify(const int &p,const int &b,const int &e,const int &x) {
 57             if(b==e) {
 58                 val[p]=x;
 59                 return;
 60             }
 61             const int mid=(b+e)>>1;
 62             if(x<=mid) modify(p _left,b,mid,x);
 63             if(x>mid) modify(p _right,mid+1,e,x);
 64             push_up(p);
 65         }
 66         int query(const int &p,const int &b,const int &e,const int &l,const int &r) const {
 67             if(b==l&&e==r) return val[p];
 68             const int mid=(b+e)>>1;
 69             int ret=0;
 70             if(l<=mid) ret=std::max(ret,query(p _left,b,mid,l,std::min(mid,r)));
 71             if(r>mid) ret=std::max(ret,query(p _right,mid+1,e,std::max(mid+1,l),r));
 72             return ret;
 73         }
 74     #undef _left
 75     #undef _right
 76     #undef _par
 77 };
 78 SegmentTree t;
 79 inline int query(int x) {
 80     int ret=0;
 81     while(!ret) {
 82         ret=t.query(1,1,dfn[0],dfn[top[x]],dfn[x]);
 83         x=par[top[x]];
 84     }
 85     return ret;
 86 }
 87 int main() {
 88     const int n=getint(),m=getint();
 89     for(register int i=1;i<n;i++) {
 90         const int u=getint(),v=getint();
 91         add_edge(u,v);
 92     }
 93     dfs1(1,0);
 94     dfs2(1);
 95     t.modify(1,1,n,1);
 96     for(register int i=0;i<m;i++) {
 97         const char opt=getalpha();
 98         const int x=getint();
 99         if(opt=='C') t.modify(1,1,n,dfn[x]);
100         if(opt=='Q') printf("%d\n",id[query(x)]);
101     }
102     return 0;
103 }

 

推荐阅读