树链剖分

洛谷 P3384 【模板】树链剖分

错误记录:

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

 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 }
View Code

两组数据

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

数据生成器

#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;
}
View Code

 

posted @ 2018-03-21 00:22  hehe_54321  阅读(150)  评论(0编辑  收藏  举报
AmazingCounters.com