zoukankan      html  css  js  c++  java
  • 洛谷树剖模板题 P3384 | 树链剖分

    原题链接

    对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树

    剩下的就和树剖一样了

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define N 100010
      5 typedef long long ll;
      6 using namespace std;
      7 int ecnt,head[N],son[N],fa[N],sz[N],n,m,r,deep[N],pos[N],indx[N],tot,op,back[N],top[N];
      8 ll val[N],P;
      9 struct adj
     10 {
     11     int nxt,v;
     12 }e[2*N];
     13 struct node
     14 {
     15     int l,r;
     16     ll sum,lz;
     17 }t[4*N];
     18 void add(int u,int v)
     19 {
     20     e[++ecnt].v=v;
     21     e[ecnt].nxt=head[u];
     22     head[u]=ecnt;
     23     e[++ecnt].v=u;
     24     e[ecnt].nxt=head[v];
     25     head[v]=ecnt;
     26 }
     27 void dfs1(int x,int father,int dep)
     28 {
     29     deep[x]=dep,fa[x]=father,sz[x]=1;
     30     for (int i=head[x];i;i=e[i].nxt)
     31     {
     32     int v=e[i].v;
     33     if (fa[x]==v) continue;
     34     dfs1(v,x,dep+1);
     35     sz[x]+=sz[v];
     36     if (sz[v]>sz[son[x]]) son[x]=v;
     37     }
     38 }
     39 void dfs2(int x,int TOP)
     40 {
     41     top[x]=TOP;
     42     pos[x]=++tot;
     43     indx[tot]=x;
     44     if (son[x]) dfs2(son[x],TOP);
     45     for (int i=head[x];i;i=e[i].nxt)
     46     {
     47     int v=e[i].v;
     48     if (v==fa[x] || v==son[x]) continue;
     49     dfs2(v,v);
     50     }
     51     back[x]=tot;
     52 }
     53 void pushdown(int p)
     54 {
     55     if (t[p].l==t[p].r || !t[p].lz) return;
     56     int w=t[p].lz;
     57     t[p<<1].sum=(t[p<<1].sum+w*(t[p<<1].r-t[p].l+1)%P)%P;
     58     t[p<<1|1].sum=(t[p<<1|1].sum+w*(t[p<<1|1].r-t[p<<1|1].l+1)%P)%P;
     59     t[p<<1].lz+=w;
     60     t[p<<1].lz%=P;
     61     t[p<<1|1].lz+=w;
     62     t[p<<1|1].lz%=P;
     63     t[p].lz=0;
     64 }
     65 void pushup(int p)
     66 {
     67     t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%P;
     68 }
     69 void build(int p,int l,int r)
     70 {
     71     t[p].l=l,t[p].r=r,t[p].lz=0;
     72     if (l!=r)
     73     {
     74     int mid=l+r>>1;
     75     build(p<<1,l,mid);
     76     build(p<<1|1,mid+1,r);
     77     pushup(p);
     78     }
     79     else
     80     t[p].sum=val[indx[l]]%P;
     81 }
     82 void modify(int p,int l,int r,int w)
     83 {
     84     if (t[p].l==l && t[p].r==r)
     85     {
     87     t[p].sum+=w*(t[p].r-t[p].l+1);
     88     t[p].lz+=w;
     89     return ;
     90     }
     91     pushdown(p);
     92     int mid=t[p].l+t[p].r>>1;
     93     if (r<=mid) modify(p<<1,l,r,w);
     94     else if (l>mid) modify(p<<1|1,l,r,w);
     95     else modify(p<<1,l,mid,w),modify(p<<1|1,mid+1,r,w);
     96     pushup(p);
     97 }
     98 ll query(int p,int l,int r)
     99 {
    100     if (t[p].l==l && t[p].r==r)
    101     return t[p].sum%P;
    102     int mid=t[p].l+t[p].r>>1;
    103     pushdown(p);
    104     if (r<=mid) return query(p<<1,l,r)%P;
    105     if (l>mid) return query(p<<1|1,l,r)%P;
    106     return (query(p<<1,l,mid)+query(p<<1|1,mid+1,r))%P;
    107 }
    108 void pathInc(int u,int v,int w)
    109 {
    110     while (top[u]!=top[v])
    111     {
    112     if (deep[top[u]]<deep[top[v]]) swap(u,v);
    113     modify(1,pos[top[u]],pos[u],w);
    114     u=fa[top[u]];
    115     }
    116     if (deep[u]>deep[v]) swap(u,v);
    117     modify(1,pos[u],pos[v],w);
    118 }
    119 ll pathQuery(int u,int v)
    120 {
    121     ll ret=0;
    122     while (top[u]!=top[v])
    123     {
    124     if (deep[top[u]]<deep[top[v]]) swap(u,v);
    125     ret=(ret+query(1,pos[top[u]],pos[u]))%P;
    126     u=fa[top[u]];
    127     }
    128     if (deep[u]>deep[v]) swap(u,v);
    129     return (ret+query(1,pos[u],pos[v]))%P;
    130 }
    131 int main()
    132 {
    133     scanf("%d%d%d%lld",&n,&m,&r,&P);
    134     for (int i=1;i<=n;i++)
    135     scanf("%lld",&val[i]);
    136     for (int i=1,u,v;i<n;i++)
    137     scanf("%d%d",&u,&v),add(u,v);
    138     dfs1(r,0,0);
    139     dfs2(r,r);
    140     build(1,1,n);
    141     for (int i=1,x,y,z;i<=m;i++)
    142     {
    143     scanf("%d",&op);
    144     if (op==1)
    145         scanf("%d%d%d",&x,&y,&z),pathInc(x,y,z);
    146     else if (op==2)
    147         scanf("%d%d",&x,&y),printf("%lld
    ",pathQuery(x,y));
    148     else if (op==3)
    149         scanf("%d%d",&x,&z),modify(1,pos[x],back[x],z);
    150     else scanf("%d",&x),printf("%lld
    ",query(1,pos[x],back[x]));
    151     }
    152     return 0;
    153 }
  • 相关阅读:
    关于宿命论的一点杂想
    关于平权意识
    《天语物道:李政道评传》
    这段时间的杂想
    Spring-Cloud简易全家桶实践
    spring-boot-starter实践
    docker 本地环境安装流程和基本指令
    SpringBoot启动关键点解析 及启动日志追溯
    Bean加载机制解读
    Spring Boot 启动机制源码阅读(粗略)
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7892142.html
Copyright © 2011-2022 走看看