模板-树链剖分

来源:互联网 发布:软件外包项目合同 编辑:程序博客网 时间:2024/04/30 02:40
#define MAXN 50010  #define L(u) (u<<1)  #define R(u) (u<<1|1)    //写在类里面爆栈  int n, m, q;  int tim;       //时间戳  int num[MAXN]; //树上每个节点的初始值  int siz[MAXN]; //siz[u]表示以u为根的子树的节点数  int top[MAXN]; //树链上深度最小的点  int son[MAXN]; //重儿子  int dep[MAXN]; //深度  int tid[MAXN]; //节点的时间戳  int _tid[MAXN]; //tid[i]=j表示时间戳为i的节点是j  int father[MAXN]; //父节点  bool vis[MAXN];  vector<int> edge[MAXN];    void init(int n)  {      for(int i = 1; i <= n; i++)      {          siz[i] = top[i] = son[i] = 0;          dep[i] = tid[i] = _tid[i] = father[i] = 0;          vis[i] = false;          tim = 0; //时间戳          edge[i].clear();      }  }    void addedge(int u, int v) //无根树加双向边  {      edge[u].push_back(v);      edge[v].push_back(u);  }    //树链剖分  dfs1(1,0)void dfs1(int u, int pre)  {      vis[u] = true;      siz[u] = 1;      father[u] = pre;      dep[u] = dep[pre] + 1; //注意根节点比较特殊      int sz = edge[u].size();      for(int i = 0; i < sz; i++)      {          int v = edge[u][i];          if(v != father[u] && vis[v] == false)          {              dfs1(v, u);              siz[u] += siz[v];              if(son[u] == 0) son[u] = v;              else if(siz[son[u]] < siz[v]) son[u] = v;          }      }  }    //注意清空vis,dfs2(1,1)void dfs2(int u, int tp)  {      vis[u] = true;      tid[u] = ++tim;      _tid[tim] = u;      top[u] = tp;      if(son[u] != 0)          dfs2(son[u], tp); //同一条重链的顶部相同        int sz = edge[u].size();      for(int i = 0; i < sz; i++)      {          int v = edge[u][i];          if(v != father[u] && v != son[u] && vis[v] == false) //注意去掉重儿子              dfs2(v, v);      }  }    void update(int u, int l, int r, int v); //线段树的更新函数    void change(int x, int y, int val)  {      while(top[x] != top[y])      {          if(dep[top[x]] < dep[top[y]])              swap(x, y);          update(1, tid[top[x]], tid[x], val); //dfs2时顶部先访问,故tid[top]较小          x = father[top[x]]; //因为top[x]->x路径上的所有点已经被更新了      }        if(dep[x] > dep[y]) //同一条重链上深度小的tid小          swap(x, y);      update(1, tid[x], tid[y], val);  }      //线段树部分  

0 0
原创粉丝点击