树链剖分
错误记录:
1.线段树(54行写成dat[num]=(dat[num]+x)%md;,缺少61行,缺少58行pushdown)
2.113、127行缺少对于L>R的特判
3.以前额外记了一个数组ou[i]表示i子树的出时间戳,然而可以直接用id[i]+sz[i]-1得到
来看看树剖我还犯过哪些错吧:
线段树空间没开够
1.分清pos[a],arr[a]
2.复制的时候没有将所有需要改的改掉
3.链操作的最后一步没有a!=b或其他的判断语句,直接查询
4.链操作不是dep[a]<dep[b],应为dep[top[a]]<dep[top[b]]这里是比较链顶点的深度,相当于比较两个点向上跳一次之后的深度,而不是自身的深度
5.线段树建树时,注意线段树上点的下标是num而不是l,原数据一定要按a[arr[l]]取
6.各个取最大值的函数初始值要为-inf,而各个取和的函数初始值要为0
1.程序首行误与点分搞混,加了一句sz[0]=inf
2.dfs1中没有sz[u]=1
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 struct E 6 { 7 LL to,nxt; 8 }e[200100]; 9 LL f1[100100],ne; 10 LL n,q,root,md; 11 LL a[100100],sz[100100],ff[100100],hson[100100],tp[100100],dep[100100]; 12 LL arr[100100],id[100100]; 13 namespace SegT 14 { 15 #define mid ((l+r)>>1) 16 #define lc (num<<1) 17 #define rc (num<<1|1) 18 LL dat[300100],addv[300100]; 19 LL L,R,x; 20 void build(LL l,LL r,LL num) 21 { 22 if(l==r) 23 { 24 dat[num]=a[arr[l]]%md; 25 return; 26 } 27 build(l,mid,lc);build(mid+1,r,rc); 28 dat[num]=(dat[lc]+dat[rc])%md; 29 } 30 void pd(LL l,LL r,LL num) 31 { 32 if(addv[num]) 33 { 34 dat[lc]=(dat[lc]+(mid-l+1)*addv[num])%md; 35 dat[rc]=(dat[rc]+(r-mid)*addv[num])%md; 36 addv[lc]=(addv[lc]+addv[num])%md; 37 addv[rc]=(addv[rc]+addv[num])%md; 38 addv[num]=0; 39 } 40 } 41 LL query(LL l,LL r,LL num) 42 { 43 if(L<=l&&r<=R) return dat[num]; 44 pd(l,r,num); 45 LL ans=0; 46 if(L<=mid) ans=(ans+query(l,mid,lc))%md; 47 if(mid<R) ans=(ans+query(mid+1,r,rc))%md; 48 return ans; 49 } 50 void addx(LL l,LL r,LL num) 51 { 52 if(L<=l&&r<=R) 53 { 54 dat[num]=(dat[num]+(r-l+1)*x)%md; 55 addv[num]=(addv[num]+x)%md; 56 return; 57 } 58 pd(l,r,num); 59 if(L<=mid) addx(l,mid,lc); 60 if(mid<R) addx(mid+1,r,rc); 61 dat[num]=(dat[lc]+dat[rc])%md; 62 } 63 #undef mid 64 #undef lc 65 #undef rc 66 } 67 void dfs1(LL u) 68 { 69 sz[u]=1; 70 for(LL k=f1[u];k;k=e[k].nxt) 71 if(e[k].to!=ff[u]) 72 { 73 ff[e[k].to]=u; 74 dep[e[k].to]=dep[u]+1; 75 dfs1(e[k].to); 76 sz[u]+=sz[e[k].to]; 77 if(sz[hson[u]]<sz[e[k].to]) hson[u]=e[k].to; 78 } 79 } 80 void dfs2(LL u) 81 { 82 arr[++arr[0]]=u;id[u]=arr[0]; 83 tp[u]=u==hson[ff[u]]?tp[ff[u]]:u; 84 if(hson[u]) dfs2(hson[u]); 85 for(LL k=f1[u];k;k=e[k].nxt) 86 if(e[k].to!=ff[u]&&e[k].to!=hson[u]) 87 { 88 dfs2(e[k].to); 89 } 90 } 91 int main() 92 { 93 LL i,x,y,idx,ans; 94 scanf("%lld%lld%lld%lld",&n,&q,&root,&md); 95 for(i=1;i<=n;i++) scanf("%lld",&a[i]); 96 for(i=1;i<n;i++) 97 { 98 scanf("%lld%lld",&x,&y); 99 e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne; 100 e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne; 101 } 102 dfs1(root);dfs2(root); 103 SegT::build(1,arr[0],1); 104 while(q--) 105 { 106 scanf("%lld",&idx); 107 if(idx==1) 108 { 109 scanf("%lld%lld%lld",&x,&y,&SegT::x); 110 while(tp[x]!=tp[y]) 111 { 112 if(dep[tp[x]]<dep[tp[y]]) swap(x,y); 113 SegT::L=id[x],SegT::R=id[tp[x]];if(SegT::L>SegT::R) swap(SegT::L,SegT::R); 114 SegT::addx(1,arr[0],1); 115 x=ff[tp[x]]; 116 } 117 SegT::L=id[x],SegT::R=id[y]; 118 if(SegT::L>SegT::R) swap(SegT::L,SegT::R); 119 SegT::addx(1,arr[0],1); 120 } 121 else if(idx==2) 122 { 123 scanf("%lld%lld",&x,&y);ans=0; 124 while(tp[x]!=tp[y]) 125 { 126 if(dep[tp[x]]<dep[tp[y]]) swap(x,y); 127 SegT::L=id[x],SegT::R=id[tp[x]];if(SegT::L>SegT::R) swap(SegT::L,SegT::R); 128 ans=(ans+SegT::query(1,arr[0],1))%md; 129 x=ff[tp[x]]; 130 } 131 SegT::L=id[x],SegT::R=id[y]; 132 if(SegT::L>SegT::R) swap(SegT::L,SegT::R); 133 ans=(ans+SegT::query(1,arr[0],1))%md; 134 printf("%lld\n",ans); 135 } 136 else if(idx==3) 137 { 138 scanf("%lld%lld",&x,&SegT::x); 139 SegT::L=id[x],SegT::R=id[x]+sz[x]-1,SegT::addx(1,arr[0],1); 140 } 141 else if(idx==4) 142 { 143 scanf("%lld",&x); 144 SegT::L=id[x],SegT::R=id[x]+sz[x]-1,ans=SegT::query(1,arr[0],1)%md; 145 printf("%lld\n",ans); 146 } 147 } 148 return 0; 149 }
树剖lca
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 struct E 6 { 7 LL to,nxt; 8 }e[1000100]; 9 LL f1[500100],ne; 10 LL n,q,root,md; 11 LL a[500100],sz[500100],ff[500100],hson[500100],tp[500100],dep[500100]; 12 LL arr[500100],id[500100]; 13 void dfs1(LL u) 14 { 15 sz[u]=1; 16 for(LL k=f1[u];k;k=e[k].nxt) 17 if(e[k].to!=ff[u]) 18 { 19 ff[e[k].to]=u; 20 dep[e[k].to]=dep[u]+1; 21 dfs1(e[k].to); 22 sz[u]+=sz[e[k].to]; 23 if(sz[hson[u]]<sz[e[k].to]) hson[u]=e[k].to; 24 } 25 } 26 void dfs2(LL u) 27 { 28 arr[++arr[0]]=u;id[u]=arr[0]; 29 tp[u]=u==hson[ff[u]]?tp[ff[u]]:u; 30 if(hson[u]) dfs2(hson[u]); 31 for(LL k=f1[u];k;k=e[k].nxt) 32 if(e[k].to!=ff[u]&&e[k].to!=hson[u]) 33 { 34 dfs2(e[k].to); 35 } 36 } 37 int main() 38 { 39 LL i,x,y; 40 scanf("%lld%lld%lld",&n,&q,&root); 41 for(i=1;i<n;i++) 42 { 43 scanf("%lld%lld",&x,&y); 44 e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne; 45 e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne; 46 } 47 dfs1(root);dfs2(root); 48 while(q--) 49 { 50 scanf("%lld%lld",&x,&y); 51 while(tp[x]!=tp[y]) 52 { 53 if(dep[tp[x]]<dep[tp[y]]) swap(x,y); 54 x=ff[tp[x]]; 55 } 56 if(dep[x]<dep[y]) swap(x,y); 57 printf("%lld\n",y); 58 } 59 return 0; 60 }
两组数据
5 5 1 23333333 5 7 3 4 3 5 1 4 3 1 4 5 2 2 4 2 1 2 5 2 2 4 5 4 5 3 3 1
5 5 4 23333333 7 9 4 9 2 2 4 3 5 1 3 2 3 2 2 5 1 4 3 5 1 1 5 6 4 4 4 5
数据生成器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<iostream> #include<algorithm> #include<ctime> #include<cstdlib> using namespace std; int fa[100100]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} int main() { int t,i,z,idx; cin>>t;srand(t); int n=5,m=5,root=rand()%5+1,md=23333333; int x,y,fx,fy; printf("%d %d %d %d\n",n,m,root,md); for(i=1;i<=n;i++) fa[i]=i; for(i=1;i<=n;i++) printf("%d ",rand()%10); puts(""); for(i=1;i<n;i++) { do{ x=rand()%n+1,y=rand()%n+1; fx=find(x);fy=find(y); }while(fx==fy); fa[fx]=fy;printf("%d %d\n",x,y); } for(i=1;i<=m;i++) { x=rand()%n+1,y=rand()%n+1,z=rand()%10; idx=rand()%4+1;printf("%d ",idx); if(idx==1) { printf("%d %d %d\n",x,y,z); } else if(idx==2) { printf("%d %d\n",x,y); } else if(idx==3) { printf("%d %d\n",x,z); } else if(idx==4) { printf("%d\n",x); } } return 0; }