• 树链剖分模板


      1 #include<cstdio>
      2 #include<iostream>
      3 #include<vector>
      4 #define tx top[x]
      5 #define ty top[y]
      6 #define ls o<<1
      7 #define rs o<<1|1
      8 #define M ((L+R)>>1)
      9 using namespace std;
     10 const int maxn = 100010;
     11 
     12 int n, m, P ,root, tot;
     13 int A[maxn], fa[maxn], deep[maxn], num[maxn], son[maxn], ID[maxn], top[maxn], fID[maxn];
     14 int sumv[maxn*4],addv[maxn*4];
     15 vector<int> G[maxn];
     16 
     17 void addedge(int x,int y) {
     18     G[x].push_back(y);
     19 }
     20 
     21 int dfs1(int x,int dep) { //返回包括自己,子树的大小 
     22     deep[x] = dep;
     23     int ret = 1;
     24     int len = G[x].size();
     25     int MX = 0;
     26     for(int i = 0;i < len;i++) {
     27         int tp = G[x][i];
     28         if(fa[x] == tp) continue;
     29         fa[tp] = x;
     30         int back = dfs1(tp,dep+1);
     31         if(back > MX) {
     32             son[x] = tp;
     33             MX = back;    
     34         } 
     35         ret += back;
     36     }
     37     num[x] = ret;
     38     return ret;
     39 }
     40 
     41 void dfs2(int x) {
     42     if(x == 0) return;
     43     ID[x] = ++tot;
     44     fID[tot] = x;
     45     if(son[fa[x]] == x) top[x] = top[fa[x]];
     46     else top[x] = x; 
     47     int len = G[x].size();
     48     dfs2(son[x]);
     49     for(int i = 0;i < len;i++) {
     50         int tp = G[x][i];
     51         if(tp != fa[x] && tp != son[x]) dfs2(tp);
     52     }
     53 }
     54 
     55 inline void build(int o,int L,int R) {
     56     if(L == R) {
     57         sumv[o] = A[fID[L]]%P;
     58         return;
     59     }
     60     build(ls,L,M);
     61     build(rs,M+1,R);
     62     sumv[o] = (sumv[ls] + sumv[rs])%P;
     63 }
     64 
     65 inline void pushdown(int o,int L,int R) {
     66     (addv[ls] += addv[o])%=P;
     67     (addv[rs] += addv[o])%=P;
     68     (sumv[ls] += addv[o]*(M-L+1))%=P;
     69     (sumv[rs] += addv[o]*(R-M))%=P;
     70     addv[o] = 0;
     71 }
     72 
     73 int ql,qr,qa;
     74 inline void update(int o,int L,int R) {
     75     if(ql <= L && R <= qr) {
     76         (addv[o] += qa)%=P;
     77         (sumv[o] += qa*(R-L+1))%=P;
     78         return;
     79     }
     80     pushdown(o,L,R);
     81     if(ql <= M) update(ls,L,M);
     82     if(qr > M) update(rs,M+1,R);
     83     sumv[o] = (sumv[ls] + sumv[rs])%P;
     84 }
     85 
     86 inline int query(int o,int L,int R) {
     87     if(ql <= L && R <= qr) return sumv[o]%P;
     88     int ret = 0;
     89     pushdown(o,L,R);
     90     if(ql <= M) (ret += query(ls,L,M))%=P;
     91     if(qr > M) (ret += query(rs,M+1,R))%=P;
     92     return ret%P; 
     93 }
     94 
     95 
     96 int LCA(int x,int y) {
     97     int ret = 0;
     98     while(tx != ty) {
     99         if(deep[tx] >= deep[ty]) {
    100             //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链 
    101             ql = ID[tx], qr = ID[x];//下闭上开 
    102             (ret += query(1,1,n))%=P; 
    103             x = fa[tx];    
    104         }
    105         else {
    106             ql = ID[ty], qr = ID[y];
    107             (ret += query(1,1,n))%=P;
    108             y = fa[ty];    
    109         }
    110     }
    111 
    112     if(x == y) {
    113         ql = ID[x],qr = ql;
    114         (ret += query(1,1,n))%=P;
    115         return ret;
    116     }
    117      if(deep[x] > deep[y]) swap(x,y);
    118     ql = ID[x], qr = ID[y]; 
    119      (ret += query(1,1,n))%=P;
    120   return ret;
    121 }
    122 
    123 void LCA_add(int x,int y,int k) {
    124     qa = k%P;
    125     while(tx != ty) {
    126         if(deep[tx] >= deep[ty]) {
    127             //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链 
    128             ql = ID[tx], qr = ID[x];//下闭上开 
    129             update(1,1,n); 
    130             x = fa[tx];    
    131         }
    132         else {
    133             ql = ID[ty], qr = ID[y];
    134             update(1,1,n);
    135             y = fa[ty];    
    136         }
    137     }
    138 
    139     if(x == y) {
    140         ql = ID[x],qr = ql;
    141         update(1,1,n);
    142         return;
    143     }
    144      if(deep[x] > deep[y]) swap(x,y);
    145     ql = ID[x], qr = ID[y]; 
    146      update(1,1,n);
    147 }
    148 
    149 int main() {
    150     scanf("%d %d %d %d",&n, &m, &root, &P);
    151     for(int i = 1;i <= n;i++) scanf("%d",A+i);
    152     for(int i = 1,x,y;i < n;i++) {
    153         scanf("%d%d",&x,&y);
    154         addedge(x,y);
    155         addedge(y,x);
    156     }
    157 
    158     dfs1(root,1);
    159     dfs2(root);
    160     build(1,1,n);
    161 
    162     for(int i = 1,x,l,r,z;i <= m;i++) {
    163         scanf("%d",&x);
    164         if(x == 1) {
    165             scanf("%d%d%d",&l,&r,&z);
    166             LCA_add(l,r,z);
    167         } else if(x == 2) {
    168             scanf("%d%d",&l,&r);
    169             printf("%d
    ",LCA(l,r));
    170         } else if(x == 3) {
    171             scanf("%d%d",&l,&z);
    172             ql = ID[l],qr = ql+num[l]-1,qa=z;
    173             update(1,1,n);
    174         } else {
    175             scanf("%d",&z);
    176             ql = ID[z],qr = ql + num[z]-1;
    177             printf("%d
    ",query(1,1,n));
    178         }
    179     }
    180     return 0;
    181 } 
  • 相关阅读:
    Css颜色定义的方法汇总color属性设置方式
    关于css中的align-content属性详解
    关于char 指针变量char *=p;这个语句的输出问题
    事件绑定3
    事件绑定2
    事件绑定1
    XPath 初步讲解
    JSON初探
    CSS 媒体类型
    CSS Positioning(定位)
  • 原文地址:https://www.cnblogs.com/frankscode/p/9533091.html
Copyright © 2020-2023  润新知