您的位置:首页 > 其它

洛谷树剖模板题 P3384 | 树链剖分

2017-11-24 19:53 513 查看

原题链接

对于以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
,son
,fa
,sz
,n,m,r,deep
,pos
,indx
,tot,op,back
,top
;
8 ll val
,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

.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\n",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\n",query(1,pos[x],back[x])); 151 } 152 return 0; 153 }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: