社区讨论

树剖,但是连样例都输不进去

P3384【模板】重链剖分 / 树链剖分参与者 3已保存回复 13

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
13 条
当前快照
1 份
快照标识符
@lo8hvpdl
此快照首次捕获于
2023/10/27 18:53
2 年前
此快照最后确认于
2023/10/27 18:53
2 年前
查看原帖
CPP
#include<stdio.h>
#include<vector>
using namespace std;

int n,m,r,p;
int dfn[200086],rfn[200086],fa[200086],siz[200086],top[200086],hevs[200086],dep[200086];
vector<int>e[200086];
int temp;

struct node{
    int l,r;
    long long val,lzd;
}te[8000086];
int a[100086];
void t_build(int l,int r,int now)
{
    te[now].l=l;
    te[now].r=r;
    te[now].val=te[now].lzd=0;
    if(l!=r)
    {
        int mid=(l+r)/2;
        t_build(l,mid,now*2);
        t_build(mid+1,r,now*2+1);
        te[now].val=te[now*2].val+te[now*2+1].val;
    }
    else te[now].val=a[dfn[l]];
    te[now].val%=p;
}
inline void lzd_down(int now)
{
    if(te[now].lzd)
    {
        te[now*2].val+=te[now].lzd*(te[now*2].r-te[now*2].l+1);
        te[now<<1].val%=p;
        te[now*2+1].val+=te[now].lzd*(te[now*2+1].r-te[now*2+1].l+1);
        te[(now<<1)|1].val%=p;
        te[now*2].lzd+=te[now].lzd;
        te[now<<1].lzd%=p;
        te[now*2+1].lzd+=te[now].lzd;
        te[(now<<1)|1].lzd%=p;
        te[now].lzd=0;
    }
}
void add(int now,int l,int r,long long val)
{
    if(l<=te[now].l&&r>=te[now].r)
    {
        te[now].lzd+=val;
        te[now].lzd%=p;
        te[now].val+=(te[now].r-te[now].l+1)*val;
        te[now].val%=p;
        return;
    }
    int mid=(te[now].l+te[now].r)/2;
    lzd_down(now);
    if(l<=mid)
        add(now*2,l,r,val);
    if(mid+1<=r)
        add(now*2+1,l,r,val);
    te[now].val=te[now*2].val+te[now*2+1].val;
    te[now].val%=p;
}
long long search(int l,int r,int now)
{
    if(l<=te[now].l&&r>=te[now].r)
        return te[now].val;
    int mid=(te[now].l+te[now].r)/2;
    long long ans=0;
    lzd_down(now);
    if(l<=mid)
        ans+=search(l,r,now*2),ans%=p;
    if(mid+1<=r)
        ans+=search(l,r,now*2+1),ans%=p;
    return ans;
}
//线段树板子

void dfs1(int now,int f,int deep)
{
    siz[now]=1;
    fa[now]=f;
    dep[now]=deep;
    for(int i=0;i<e[now].size();i++)
    {
        int oth=e[now][i];
        if(oth!=f)
        {
            dfs1(oth,now,deep+1);
            siz[now]+=siz[oth];
            if(siz[oth]>siz[hevs[now]])
                hevs[now]=oth;
        }
    }
}
void dfs2(int now,int f)
{
    if(hevs[now])
    {
        dfn[hevs[now]]=++temp;
        top[hevs[now]]=top[now];
        rfn[temp]=hevs[now];
        dfs2(hevs[now],now);
    }
    for(int i=0;i<e[now].size();i++)
    {
        int oth=e[now][i];
        if(!top[oth])
        {
            dfn[oth]=++temp;
            rfn[temp]=oth;
            top[oth]=oth;
            dfs2(oth,now);
        }
    }
}
//树剖

int main()
{
    scanf("%d%d%d%d",&n,&m,&r,&p);
    for(int i=1;i<=n;i++)
        scanf("%d",a+i);
    for(int i=1;i<n;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        e[a].push_back(b);
        e[b].push_back(a);
    }
    dfn[r]=temp=1;
    rfn[1]=r;
    top[r]=r;
    dfs1(r,0,1);
    dfs2(r,0);
    t_build(1,n,1);
    /*for(int i=1;i<=n;i++)
    {
        printf("%d:",dfn[i]);
        for(int j=0;j<e[i].size();j++)
            printf("%d ",e[i][j]);
        printf("    %d",hevs[i]);
        printf("\n");
    }*/
    while(m--)
    {
        int op,x,y;
        long long z;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%lld",&x,&y,&z);
            z%=p;
            while(top[x]!=top[y])
            {
                if(dep[top[x]]<dep[top[y]])
                    x^=y,y^=x,x^=y;
                add(1,dfn[top[x]],dfn[x],z);
                x=fa[top[x]];
            }
            if(dep[x]>dep[y])
                x^=y,y^=x,x^=y;
            add(1,dfn[x],dfn[y],z);
        }
        else if(op==2)
        {
            long long ans=0;
            scanf("%d%d",&x,&y);
            while(top[x]!=top[y])
            {
                if(dep[top[x]]<dep[top[y]])
                    x^=y,y^=x,x^=y;
                ans+=search(1,dfn[top[x]],dfn[x]);
                ans%=p;
                x=fa[top[x]];
            }
            if(dep[x]>dep[y])
                x^=y,y^=x,x^=y;
            ans+=search(1,dfn[x],dfn[y]);
            ans%=p;
            printf("%lld\n",ans);
        }
        else if(op==3)
        {
            scanf("%d%lld",&x,&z);
            z%=p;
            add(1,dfn[x],dfn[x]+siz[x]-1,z);
        }
        else
        {
            scanf("%d",&x);
            printf("%lld\n",search(1,dfn[x],dfn[x]+siz[x]-1));
        }
    }
    return 0;
}

样例: 5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
输到"4 5"时就会卡炸掉,估计是建树或者是search的问题,但具体怎么回事就不知道了

救救孩子吧!

回复

13 条回复,欢迎继续交流。

正在加载回复...