bzoj4551: [Tjoi2016&Heoi2016]树(树链剖分)


4551: [Tjoi2016&Heoi2016]树

题目:传送门


题解:

   一道树剖裸题

   线段树的c值维护新编号最大的已被标记的节点。

   用一个数组转化新编号为旧编号(就是因为这个小细节打错ORZ)

   然后就是一顿乱撸

  


代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define N 110000
  7 using namespace std;
  8 struct node
  9 {
 10     int x,y,next;
 11 }a[N*2];int len,last[N];
 12 void ins(int x,int y)
 13 {
 14     len++;a[len].x=x;a[len].y=y;
 15     a[len].next=last[x];last[x]=len;
 16 }
 17 struct trnode
 18 {
 19     int l,r,c,lc,rc;
 20 }tr[N*2];int trlen;
 21 void bt(int l,int r)
 22 {
 23     int now=++trlen;
 24     tr[now].l=l;tr[now].r=r;tr[now].c=-1;
 25     tr[now].lc=tr[now].rc=-1;
 26     if(l<r)
 27     {
 28         int mid=(l+r)/2;
 29         tr[now].lc=trlen+1;bt(l,mid);
 30         tr[now].rc=trlen+1;bt(mid+1,r);
 31     }
 32 }
 33 int dep[N],tot[N],ys[N],son[N],fa[N],top[N],id[N],z;
 34 void pre_tree_node(int x)
 35 {
 36     tot[x]=1;son[x]=0;
 37     for(int k=last[x];k;k=a[k].next)
 38     {
 39         int y=a[k].y;
 40         if(y!=fa[x])
 41         {
 42             fa[y]=x;
 43             dep[y]=dep[x]+1;
 44             pre_tree_node(y);
 45             tot[x]+=tot[y];
 46             if(tot[y]>tot[son[x]])son[x]=y;
 47         }
 48     }
 49 }
 50 void pre_tree_edge(int x,int tp)
 51 {
 52     ys[x]=++z;top[x]=tp;id[z]=x;
 53     if(son[x]!=0)pre_tree_edge(son[x],tp);
 54     for(int k=last[x];k;k=a[k].next)
 55     {
 56         int y=a[k].y;
 57         if(y!=fa[x] && y!=son[x])
 58             pre_tree_edge(y,y);
 59     }
 60 }
 61 void change(int now,int x)
 62 {
 63     if(tr[now].l==tr[now].r){tr[now].c=x;return ;}
 64     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
 65     if(x<=mid)change(lc,x);
 66     else change(rc,x);
 67     tr[now].c=max(tr[lc].c,tr[rc].c);
 68 }
 69 int find_x(int now,int l,int r)
 70 {
 71     if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
 72     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
 73     if(r<=mid)return find_x(lc,l,r);
 74     else if(l>mid)return find_x(rc,l,r);
 75     else return max(find_x(lc,l,mid),find_x(rc,mid+1,r));
 76 }
 77 int get_id(int x)
 78 {
 79     int T=top[x];
 80     while(1)
 81     {
 82         int k=find_x(1,ys[T],ys[x]);
 83         if(k==-1)
 84         {
 85             x=fa[T];
 86             T=top[x];
 87         }
 88         else return id[k];
 89     }
 90 }
 91 char s[5];
 92 int main()
 93 {
 94     int n,m;
 95     scanf("%d%d",&n,&m);
 96     for(int i=1;i<n;i++)
 97     {
 98         int x,y;
 99         scanf("%d%d",&x,&y);
100         ins(x,y);
101     }
102     dep[1]=0;fa[1]=0;pre_tree_node(1);z=0;pre_tree_edge(1,1);trlen=0;bt(1,z);change(1,ys[1]);
103     while(m--)
104     {
105         int x;
106         scanf("%s%d",s+1,&x);
107         if(s[1]=='Q')printf("%d\n",get_id(x));
108         else change(1,ys[x]);
109     }
110     return 0;
111 }

优质内容筛选与推荐>>
1、find命令
2、高强度学习训练第十二天总结:Java hashCode和equals的关系
3、feign调用超时
4、【IntelliJ IDEA】idea部署服务到Tomcat的工作原理
5、读取文件


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号