• [HEOI2016/TJOI2016]树


    题目大意:
      给定一棵$n(nle10^5)$个结点的以$1$为根的树,初始时$1$为标记结点。有$m(mle10^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
    ",id[query(x)]);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    (转)C3P0连接池配置和实现详解
    (转)jquery插件Validate的使用
    二叉树和翻转二叉树
    利用@media screen实现网页布局的自适应
    (转)防止SQL注入的五种方法
    java代码规范
    Java泛型-类型擦除
    js中的isNaN()
    (转)sublime 一些常用功能和快捷键
    (转)java中不常见的关键字:strictfp,transient
  • 原文地址:https://www.cnblogs.com/skylee03/p/8675933.html
Copyright © 2020-2023  润新知