• 第五章总结


    二叉树

             定义很重要,没错,我就默一遍吧。(最简单的不写)

                  结点的度:结点拥有的子树个数(分支数);

        祖先:根到该结点所经分支上的所有的结点;

        树的度:树内结点度的最大值;

        树的高度(深度):树的最大层次;

      然后是二叉树的性质,也很重要我也来一遍吧。

     

     

     

     证明错了请指正!!!

      学习笔记

    树的dfs序(先序)

    题目:https://cn.vjudge.net/contest/283912#problem/J

      意思是给你一些属从关系,a  b ,代表b 是a 的上属,你可以给一个人分配任务,他和他所有下属都要做那个任务,然后可以查询一个人现在在做什么任务,无分配就输出-1;

      这题很容易想到并查集,但还可以用线段树做,通过懒惰标记来pushdowm任务,精髓是对每一个结点的子树dfs序编号,就把子树变成线性结构的一个区间了,从而可以很容易的通过递归更改任务。

      代码:

      1 #include<iostream>
      2 #include<vector>
      3 #include<cstring>
      4 #include<stdio.h>
      5 using namespace std;
      6 #define pb push_back
      7 const int N = 50005;//员工最多有那么多个
      8 
      9 vector <int> ve[N];//就建立那么多的树,ve[他]表示他为经理的一颗树
     10 bool vis[N];//用于标记数组
     11 int index;//时间戳中间变量
     12 int sta[N],en[N];//结点dfs序的开始与结束
     13 
     14 typedef struct Node{
     15     int task,lazy;
     16 }Node;
     17 Node tree[N << 2];
     18 void dfs(int k)
     19 {
     20     sta[k]=++index;
     21     int len=ve[k].size();
     22     for(int i=0;i<len;i++)
     23         dfs(ve[k][i]);
     24     en[k]=index;
     25 }
     26 
     27 void pushdown(int root)
     28 {
     29     if(tree[root].lazy )//有懒惰标记
     30     {
     31         tree[root * 2 + 1].lazy =tree[root * 2 + 2].lazy =tree[root].lazy ;//将现在结点的懒惰标记下传
     32         tree[root * 2 + 1].task =tree[root * 2 + 2].task =tree[root].task ;//下属的任务和经理相同
     33         tree[root].lazy =0;//经理的懒标记清空
     34     }
     35 }
     36 
     37 int query(int root,int l,int r,int index)//根,左,右,index是x号员工开始的时间戳
     38 {
     39     if( l==r && l==index )
     40         return tree[root].task ;
     41     pushdown(root);//对于每一次查询,更新root下面的懒标记和任务
     42     int mid=(l+r)/2;
     43     if(index<=mid)
     44     {//答案在左边
     45         return query(root*2+1,l,mid,index);
     46     }
     47     else//答案在右边
     48         return query(root*2+2,mid+1,r,index);//!!!!!!!!!!!!!!!!
     49 }
     50 
     51 void update(int root ,int l,int r,int pl,int pr,int task)//pl,pr是x号员工对应下属树的区间左和右,将他们全部更新为task
     52 {
     53     if( r<pl || pr<l)
     54         return;
     55     if(l >= pl && r <= pr )
     56     {
     57         tree[root].lazy =1;
     58         tree[root].task =task;
     59         return ;
     60     }
     61     pushdown(root);//对于没进入上面两个if,都要下传本次经理的懒标记和任务
     62     int mid=( l + r ) /2;
     63     if(pl<=mid){
     64         update(root *2+1,l,mid,pl,pr,task);
     65     }
     66     if(pr>mid)
     67     {
     68         update(root *2+2,mid+1,r,pl,pr,task);
     69     }
     70 }
     71 
     72 int main()
     73 {
     74     int cnt=0;//用于输出case的数字
     75     int t;
     76     scanf("%d",&t);
     77     while(t--)
     78     {
     79         int n;
     80         cnt++;
     81         scanf("%d",&n);
     82         for(int i=1;i<=n;i++)
     83             ve[i].clear();//先初始化全部经理树
     84         memset(vis,false,sizeof(vis));//初始化vis为负一
     85         for(int i=0;i<n-1;i++)
     86         {
     87             int u,v;
     88             cin>>u>>v;
     89             vis[u]=true;//记录的是u,下属!
     90             ve[v].pb(u);//把u放入名字为v的动态数组,表示u是v的下属
     91         }
     92         index=0;
     93 
     94         for(int i=1;i<=n;i++)
     95         {
     96             if(!vis[i]){
     97                 dfs(i);
     98                 break;
     99             }
    100         }
    101         for(int i=1;i<(N<<2);i++)
    102         {//初始化树的懒惰标记和任务
    103             tree[i].task =-1;//一开始没有任务,要输出-1
    104             tree[i].lazy =0;
    105         }
    106         printf("Case #%d:
    ",cnt);
    107 
    108         int M;
    109         cin>>M;
    110         while(M--)
    111         {
    112             char ch;
    113             cin>>ch;
    114             if(ch=='C'){//查询x号员工现在做的工作
    115                 int x;
    116                 cin>>x;
    117                 cout<<query(1,1,n,sta[x])<<endl;
    118             }
    119             else{
    120                 int x,y;
    121                 scanf("%d %d",&x,&y);
    122                 update(1,1,n,sta[x],en[x],y);//更新x的所有下属去做任务y
    123             }
    124         }
    125     }
    126     return 0;
    127 }

    目标:把主席树思想转化为代码,红黑树,字典树有时间搞搞。

         省赛前复习最小生成树,并查集,最短路径和深广搜。

        

  • 相关阅读:
    【转】win8.1下安装ubuntu
    Codeforces 1025G Company Acquisitions (概率期望)
    Codeforces 997D Cycles in Product (点分治、DP计数)
    Codeforces 997E Good Subsegments (线段树)
    Codeforces 1188E Problem from Red Panda (计数)
    Codeforces 1284E New Year and Castle Building (计算几何)
    Codeforces 1322D Reality Show (DP)
    AtCoder AGC043C Giant Graph (图论、SG函数、FWT)
    Codeforces 1305F Kuroni and the Punishment (随机化)
    AtCoder AGC022E Median Replace (字符串、自动机、贪心、计数)
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/10808818.html
Copyright © 2020-2023  润新知