bzoj4034: [HAOI2015]树上操作(树剖)
4034: [HAOI2015]树上操作
题目:传送门
题解:
树剖裸题:
麻烦一点的就只有子树修改(其实一点也不),因为子树编号连续啊,直接改段(记录编号最小和最大)
开个long long 水模版
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long LL; 8 struct node 9 { 10 int x,y,next; 11 }a[210000];int len,last[110000]; 12 void ins(int x,int y) 13 { 14 len++;a[len].x=x;a[len].y=y; 15 a[len].next=last[x];last[x]=len; 16 } 17 struct trnode 18 { 19 int l,r,lc,rc;LL c,lz; 20 trnode(){lz=0;} 21 }tr[210000];int trlen; 22 void update(int now) 23 { 24 if(tr[now].lz!=0) 25 { 26 int lc=tr[now].lc,rc=tr[now].rc; 27 if(lc!=-1)tr[lc].c+=LL(tr[lc].r-tr[lc].l+1)*tr[now].lz,tr[lc].lz+=tr[now].lz; 28 if(rc!=-1)tr[rc].c+=LL(tr[rc].r-tr[rc].l+1)*tr[now].lz,tr[rc].lz+=tr[now].lz; 29 tr[now].lz=0; 30 } 31 } 32 void bt(int l,int r) 33 { 34 int now=++trlen; 35 tr[now].l=l;tr[now].r=r;tr[now].c=0; 36 tr[now].lc=tr[now].rc=-1; 37 if(l<r) 38 { 39 int mid=(l+r)/2; 40 tr[now].lc=trlen+1;bt(l,mid); 41 tr[now].rc=trlen+1;bt(mid+1,r); 42 } 43 } 44 void change(int now,int l,int r,LL c) 45 { 46 if(tr[now].l==l && r==tr[now].r){tr[now].c+=LL(r-l+1)*c;tr[now].lz+=c;return ;} 47 int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; 48 update(now); 49 if(r<=mid)change(lc,l,r,c); 50 else if(mid+1<=l)change(rc,l,r,c); 51 else change(lc,l,mid,c),change(rc,mid+1,r,c); 52 tr[now].c=tr[lc].c+tr[rc].c; 53 } 54 LL getsum(int now,int l,int r) 55 { 56 if(tr[now].l==l && r==tr[now].r)return tr[now].c; 57 int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; 58 update(now); 59 if(r<=mid)return getsum(lc,l,r); 60 else if(mid+1<=l)return getsum(rc,l,r); 61 return getsum(lc,l,mid)+getsum(rc,mid+1,r); 62 } 63 int n,m,fa[110000],tot[110000],son[110000],dep[110000]; 64 void pre_tree_node(int x) 65 { 66 son[x]=0;tot[x]=1; 67 for(int k=last[x];k;k=a[k].next) 68 { 69 int y=a[k].y; 70 if(y!=fa[x]) 71 { 72 fa[y]=x;dep[y]=dep[x]+1; 73 pre_tree_node(y); 74 if(tot[y]>tot[son[x]])son[x]=y; 75 tot[x]+=tot[y]; 76 } 77 } 78 } 79 int tp,id,ys[110000],top[110000],L[110000],R[110000]; 80 void pre_tree_edge(int x,int tp) 81 { 82 ys[x]=++id;top[x]=tp;L[x]=id; 83 if(son[x]!=0)pre_tree_edge(son[x],tp); 84 for(int k=last[x];k;k=a[k].next) 85 { 86 int y=a[k].y; 87 if(y!=son[x] && y!=fa[x])pre_tree_edge(y,y); 88 } 89 R[x]=id; 90 } 91 LL sol(int x,int y) 92 { 93 LL ans=0;int tx=top[x],ty=top[y]; 94 while(tx!=ty) 95 { 96 if(dep[tx]>dep[ty])swap(tx,ty),swap(x,y); 97 ans+=getsum(1,ys[ty],ys[y]); 98 y=fa[ty];ty=top[y]; 99 } 100 if(x==y)return ans+getsum(1,ys[x],ys[x]); 101 else 102 { 103 if(dep[x]>dep[y])swap(x,y); 104 return ans+getsum(1,ys[x],ys[y]); 105 } 106 } 107 LL d[100000]; 108 int main() 109 { 110 scanf("%d%d",&n,&m);len=0;memset(last,0,sizeof(last)); 111 for(int i=1;i<=n;i++)scanf("%lld",&d[i]); 112 for(int i=1;i<n;i++) 113 { 114 int x,y;scanf("%d%d",&x,&y); 115 ins(x,y);ins(y,x); 116 } 117 fa[1]=0;dep[1]=0;pre_tree_node(1); 118 id=0;pre_tree_edge(1,1); 119 trlen=0;bt(1,id);for(int i=1;i<=n;i++)change(1,ys[i],ys[i],d[i]); 120 while(m--) 121 { 122 int opt,x;LL y;scanf("%d",&opt); 123 if(opt==1)scanf("%d%lld",&x,&y),change(1,ys[x],ys[x],y); 124 else if(opt==2) 125 { 126 scanf("%d%lld",&x,&y); 127 change(1,L[x],R[x],y); 128 } 129 else {scanf("%d",&x);printf("%lld\n",sol(1,x));} 130 } 131 return 0; 132 }