求助树剖,除了#1#4全WA

P3384 【模板】重链剖分/树链剖分

zhfaz123 @ 2023-03-30 13:40:27

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<iostream>
#include<vector>
#define N (int(1e5))
using namespace std;
int son[N+1],id[N+1],sz[N+1],fa[N+1],dep[N+1],dfc,top[N+1],w[N+1],nw[N+1];//树的变量
int n,m,p,q;
vector<int> edge[N+1];//图
struct g
{
    int l,r;
    long long lazy,data;
    g():l(0),r(0),lazy(0),data(0){};
}a[((N)<<2)+1];//线段树
//线段树
void build(int root,int l,int r)
{
    a[root].l=l;
    a[root].r=r;
    int mid=l+r>>1;
    if(l==r)
    {
        a[root].data=nw[l]%p;
        return ;
    }
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    a[root].data=a[root<<1].data+a[root<<1|1].data;
}
inline void push_down(int root)
{
    if(a[root].lazy)
    {
        int mid=a[root].l+a[root].r>>1;
        a[root<<1].lazy+=a[root].lazy;
        a[root<<1|1].lazy+=a[root].lazy;
        a[root<<1].data+=(a[root<<1].r-a[root<<1].l+1)*a[root].lazy;
        a[root<<1|1].data+=(a[root<<1|1].r-a[root<<1|1].l+1)*a[root].lazy;
        a[root].lazy=0;
    }
}
void add(int root,int l,int r,long long k)
{
    int mid=a[root].l+a[root].r>>1;
    if(l <= a[root].l && r >=a[root].r)
    {
        a[root].data=(a[root].data%p+k%p)%p;
        a[root].lazy=(a[root].lazy%p+k%p)%p;
        return;
    }
    push_down(root);
    if(l<=mid)add(root<<1,l,r,k);
    if(r>mid)add(root<<1|1,l,r,k);
    a[root].data=a[root<<1].data+a[root<<1|1].data;
    return ;
}
int query(int root,int l,int r)
{
    int mid=a[root].l+a[root].r>>1;
    long long ret=0;
    if(l <= a[root].l && r >=a[root].r)
    {
        return a[root].data%p;
    }
    push_down(root);
    if(l<=mid)ret=(ret%p+query(root<<1,l,r)%p)%p;
    if(r>mid)ret=(ret%p+query(root<<1|1,l,r)%p)%p;
    a[root].data=a[root<<1].data+a[root<<1|1].data;
    return ret;
}
//线段树结束
void dfs(int root,int f,int deep)
{
    fa[root]=f;
    sz[root]=1;
    dep[root]=deep;
    int hvs=-1;
    for(auto &i:edge[root])
    {
        if(i==f)
            continue;
        dfs(i,root,deep+1);
        sz[root]+=sz[i];
        if(sz[i]>hvs)
        {
            hvs=sz[i];
            son[root]=i;
        }
    }
}//第一遍dfs
void dfs2(int root,int topf)
{

    id[root]=++dfc;
    nw[id[root]]=w[root];
    top[root]=topf;
    if(!son[root]) 
        return;
    dfs2(son[root],topf);
    for(auto &i:edge[root])
    {
        if(i == son[root] || i == fa[root])
            continue;
        dfs2(i,i);
    }
}//第二遍dfs
void addpath(int x,int y,long long k)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        add(1,id[top[x]],id[x],k%p);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y])
        swap(x,y);
    add(1,id[y],id[x],k%p);
    return ;
}//增加路径和
long long querypath(int x,int y)
{
    long long ret=0;
    while(top[x] != top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        ret=(ret%p+query(1,id[top[x]],id[x])%p)%p;
        x=fa[top[x]];
    }
    if(dep[x]<dep[y])
    {
        swap(x,y);
    }
    ret=(ret%p+query(1,id[y],id[x])%p)%p;
    return ret;
}//查询路径和
void addtree(int x,long long k)
{
    add(1,id[x],id[x]+sz[x]-1,k);
}//增加子树和
long long querytree(int x)
{
    long long ret=0;
    ret=(ret%p+query(1,id[x],id[x]+sz[x]-1)%p)%p;
    return ret;
}//查询子树和
int main()
{
    scanf("%d %d %d %d",&n,&q,&m,&p);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
    }
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    dfs(m,0,1);
    dfs2(m,m);
    build(1,1,n);//建树
    for(int i=1;i<=q;i++)
    {
        int op;
        scanf("%d",&op);
        switch (op) 
        {
            case 1:
            {
                int x,y;
                long long k;
                scanf("%d %d %lld",&x,&y,&k);
                addpath(x,y,k);
                break;
            }
            case 2:
            {
                int x,y;
                scanf("%d %d",&x,&y);
                printf("%lld\n",querypath(x,y)%p);
                break;
            }
            case 3:
            {
                int x;
                long long k;
                scanf("%d %lld",&x,&k);
                addtree(x,k);
                break;
            }
            case 4:
            {
                int x;
                scanf("%d",&x);
                printf("%lld\n",querytree(x)%p);
                break;          
            }
            default:
                break;
        }
    }
    return 0;
}

by puck @ 2023-03-30 14:50:34

别的不说,首先你所有的mid就有位运算优先级问题吧


by zhfaz123 @ 2023-03-30 15:48:09

@puck 没错啊。 a+b>>1不是等于(a+b)>>1吗?


by puck @ 2023-03-30 16:16:58

@zhfaz123 优先级记反了XD,好像是add那里应该要加k*区间长度,你加的k


by zhfaz123 @ 2023-03-30 16:36:05

@puck 谢谢,改了之后就AC了


|