• 数链剖分小结


    就是把树上的路径拆成几段,然后大多按照线段树的解法解就可以了

    讲解

    http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

    模板

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<stdlib.h>
      7 #include<vector>
      8 #include<cmath>
      9 #include<queue>
     10 #include<set>
     11 using namespace std;
     12 #define N 50006
     13 #define INF 0xfffffff
     14 const double eps = 1e-8;
     15 const double pi = acos(-1.0);
     16 const double inf = ~0u>>2;
     17 /*
     18 fa[u]  u的父亲节点
     19 son[u] u的儿子节点
     20 dep[u] u的深度
     21 top[u] u所在链的深度最小的点
     22 siz[u] 以u为根的子树上的节点总数
     23 po[u] u在dfs时的时间戳
     24 */
     25 struct node
     26 {
     27     int u,v,next;
     28 } ed[N<<1];
     29 int head[N],t;
     30 int a[N];
     31 
     32 void add(int u,int v)
     33 {
     34     ed[t].u = u,ed[t].v = v;
     35     ed[t].next = head[u];
     36     head[u] = t++;
     37 }
     38 int siz[N],fa[N],son[N],dep[N],top[N],seg[N],po[N];
     39 int tp;
     40 void init()
     41 {
     42     t = 0;tp=0;
     43     memset(head,-1,sizeof(head));
     44     memset(son,-1,sizeof(son));
     45 }
     46 void dfs1(int u,int pre,int d)
     47 {
     48     dep[u] = d,fa[u] = pre,siz[u] = 1,son[u] = -1;
     49     for(int i = head[u] ; i!=-1 ; i = ed[i].next)
     50     {
     51         int v = ed[i].v;
     52         if(v!=pre)
     53         {
     54             dfs1(v,u,d+1);
     55             if(son[u]==-1||siz[son[u]]<siz[v])
     56                 son[u] = v;
     57             siz[u]+=siz[v];
     58         }
     59     }
     60 }
     61 
     62 void dfs2(int u,int pre,int tu)
     63 {
     64     top[u] = tu,po[u] = ++tp,seg[tp] = u;
     65     if(son[u]==-1) return ;
     66     dfs2(son[u],u,tu);
     67     for(int i = head[u]; i!=-1;  i =ed[i].next)
     68     {
     69         int v = ed[i].v;
     70         if(v!=fa[u]&&v!=son[u])
     71         dfs2(v,u,v);
     72     }
     73 }
     74 int s[N<<2];
     75 int n;
     76 void build(int l,int r,int w)
     77 {
     78     s[w] = 0;
     79     if(l==r)
     80     {
     81         s[w] = a[seg[l]];
     82         return ;
     83     }
     84     int m = (l+r)>>1;
     85     build(l,m,w<<1);
     86     build(m+1,r,w<<1|1);
     87 }
     88 void down(int w,int m)
     89 {
     90     if(s[w])
     91     {
     92         s[w<<1]+=s[w];
     93         s[w<<1|1]+=s[w];
     94         s[w] = 0;
     95     }
     96 }
     97 void update(int a,int b,int va,int l,int r,int w)
     98 {
     99     if(a<=l&&b>=r)
    100     {
    101         s[w]+=va;
    102         return ;
    103     }
    104     down(w,r-l+1);
    105     int m = (l+r)>>1;
    106     if(a<=m) update(a,b,va,l,m,w<<1);
    107     if(b>m) update(a,b,va,m+1,r,w<<1|1);
    108 }
    109 int query(int p,int l,int r,int w)
    110 {
    111     if(l==r)
    112     {
    113         return s[w];
    114     }
    115     down(w,r-l+1);
    116     int m = (l+r)>>1;
    117     if(p<=m) return query(p,l,m,w<<1);
    118     else return  query(p,m+1,r,w<<1|1);
    119 }
    120 void solve(int l,int r,int val)
    121 {
    122     while(top[l]!=top[r])
    123     {
    124         if(dep[top[l]]<dep[top[r]]) swap(l,r);
    125         update(po[top[l]],po[l],val,1,n,1);
    126         l = fa[top[l]];
    127     }
    128     if(dep[l]>dep[r]) swap(l,r);
    129     //对于结点值的操作
    130     update(po[l],po[r],val,1,n,1);
    131     /* 对于边权的话,需要减掉lca(l,r) 所以对seg[l]+1操作即可
    132         if(l!=r)
    133         update(po[l]+1,po[r],val,1,n,1);
    134     */
    135 }
    136 int main()
    137 {
    138     int i,m,Q;
    139     char str[20];
    140     while(scanf("%d%d%d",&n,&m,&Q)!=EOF)
    141     {
    142         init();
    143         for(i = 1; i <= n ;i++)
    144         scanf("%d",&a[i]);
    145         for(i = 1; i < n; i++)
    146         {
    147             int u,v;
    148             scanf("%d%d",&u,&v);
    149             add(u,v);
    150             add(v,u);
    151         }
    152         dfs1(1,-1,1);
    153 
    154         dfs2(1,-1,1);
    155         build(1,n,1);
    156         while(Q--)
    157         {
    158             int x,y,z;
    159             scanf("%s",str);
    160 
    161             if(str[0]=='I')
    162             {
    163                 scanf("%d%d%d",&x,&y,&z);
    164                 solve(x,y,z);
    165             }
    166             else if(str[0]=='D')
    167             {
    168                 scanf("%d%d%d",&x,&y,&z);
    169                 solve(x,y,-z);
    170             }
    171             else
    172             {
    173                 scanf("%d",&x);
    174                 printf("%d
    ",query(po[x],1,n,1));
    175             }
    176         }
    177     }
    178     return 0;
    179 }
    View Code
  • 相关阅读:
    Linux pwn入门教程(1)——栈溢出基础
    Java代码审计入门篇
    利用Burp Suite攻击Web应用
    记一次对某企业的渗透测试实战
    Python 绝技 —— UDP 服务器与客户端
    SQL注入之重新认识
    文件上传和WAF的攻与防
    phpMyAdmin 4.7.x CSRF 漏洞利用
    Powershell渗透测试系列–进阶篇
    AFN检測网络情况
  • 原文地址:https://www.cnblogs.com/shangyu/p/3710608.html
Copyright © 2020-2023  润新知