树剖模板70pts,#2#9#10MLE
查看原帖
树剖模板70pts,#2#9#10MLE
72764
JinBridge楼主2021/9/6 20:25

RT

#include<bits/stdc++.h>
using namespace std;

const int MAXN=1e5+10;
int n,m,r,tot,cnt;
int MODD,rk[MAXN],head[MAXN];
struct e{
    int to,next;
} edge[MAXN];
struct p{ //存储点的信息
    int val,dep,hson; //权值,深度,重儿子
    int size,fa,top,dfn; //子树大小,父节点,所在重链顶点,DFS 序
} node[MAXN];
struct seg_node{ //存储线段树
    int l,r,sum,add;
} tree[MAXN*4];

void add_edge(int f,int t) { //添加边
    edge[++tot].to=t;
    edge[tot].next=head[f];
    head[f]=tot;
    return;
}
void tree_build(int p,int dep) { //第一次DFS
    node[p].dep=dep;
    node[p].size=1;
    for(int i=head[p];i;i=edge[i].next) {
        if(edge[i].to!=node[p].fa) {
            node[edge[i].to].fa=p;
            tree_build(edge[i].to,dep+1);
            node[p].size+=node[edge[i].to].size;
            if(!node[p].hson||node[edge[i].to].size>node[node[p].hson].size)
                node[p].hson=edge[i].to;
        }
    }
    return;
}
void tree_composition(int p,int top) { //第二次DFS
    node[p].top=top;
    cnt++;
    node[p].dfn=cnt;
    rk[cnt]=p;
    if(!node[p].hson) {return;}
    tree_composition(node[p].hson,top);
    for(int i=head[p];i;i=edge[i].next) {
        if(edge[i].to!=node[p].hson&&
            edge[i].to!=node[p].fa)
            tree_composition(edge[i].to,edge[i].to);
    }
    return;
}
void seg_build(int p,int l,int r) { //建立线段树
    tree[p].l=l;
    tree[p].r=r;
    if(l==r) {tree[p].sum=node[rk[l]].val;return;}
    int mid=(l+r)/2;
    seg_build(2*p,l,mid);
    seg_build(2*p+1,mid+1,r);
    tree[p].sum=tree[2*p].sum+tree[2*p+1].sum;
    return;
}
void push_down(int p) { //线段树标记下传
    if(tree[p].add) {
        tree[2*p].sum=(tree[2*p].sum+tree[p].add*(tree[2*p].r-tree[2*p].l+1))%MODD;
        tree[2*p+1].sum=(tree[2*p+1].sum+tree[p].add*(tree[2*p+1].r-tree[2*p+1].l+1))%MODD;
        tree[2*p].add=(tree[2*p].add+tree[p].add)%MODD;
        tree[2*p+1].add=(tree[2*p+1].add+tree[p].add)%MODD;
        tree[p].add=0;
    }
    return;
}
void seg_add(int p,int l,int r,int v) { //线段树区间修改
    if(l<=tree[p].l&&tree[p].r<=r) {
        tree[p].add=(tree[p].add+v)%MODD;
        tree[p].sum=(tree[p].sum+v*(tree[p].r-tree[p].l+1))%MODD;
        return;
    }
    push_down(p);
    int mid=(tree[p].l+tree[p].r)/2;
    if(mid<r) seg_add(2*p+1,l,r,v);
    if(l<=mid) seg_add(2*p,l,r,v);
    tree[p].sum=(tree[2*p].sum+tree[2*p+1].sum)%MODD;
    return;
}
int seg_ask(int p,int l,int r) { //线段树区间查询
    if(l<=tree[p].l&&tree[p].r<=r) {
        return tree[p].sum;
    }
    push_down(p);
    int ret=0;
    int mid=(tree[p].l+tree[p].r)/2;
    if(mid<r) ret=(ret+seg_ask(2*p+1,l,r))%MODD;
    if(l<=mid) ret=(ret+seg_ask(2*p,l,r))%MODD;
    return ret;
}
void tree_add(int p,int v) { //p 子树上所有点权值 +v
    seg_add(1,node[p].dfn,node[p].dfn+node[p].size-1,v);
    return;
}
int tree_ask(int p) { //查询 p 子树所有点权值之和
    return seg_ask(1,node[p].dfn,node[p].dfn+node[p].size-1);
}
int route_ask(int x,int y) { //两点间最短距离上的点值求和
    int ret=0;
    while(node[x].top!=node[y].top) {
        if(node[node[x].top].dep<node[node[y].top].dep)
            swap(x,y);
        ret=(ret+seg_ask(1,node[node[x].top].dfn,node[x].dfn))%MODD;
        x=node[node[x].top].fa;
    }
    if(node[x].dep>node[y].dep)
        swap(x,y);
    ret=(ret+seg_ask(1,node[x].dfn,node[y].dfn))%MODD;
    return ret;
}
void route_change(int x,int y,int v) { //两点间最短距离上的点值修改
    while(node[x].top!=node[y].top) {
        if(node[node[x].top].dep<node[node[y].top].dep)
            swap(x,y);
        seg_add(1,node[node[x].top].dfn,node[x].dfn,v);
        x=node[node[x].top].fa;
    }
    if(node[x].dep>node[y].dep)
        swap(x,y);
    seg_add(1,node[x].dfn,node[y].dfn,v);
    return;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&r,&MODD);
    for(int i=1;i<=n;i++) {
        scanf("%d",&node[i].val);
    }
    for(int i=1;i<n;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        add_edge(x,y);
        add_edge(y,x);
    }
    tree_build(r,1);
    tree_composition(r,r);
    seg_build(1,1,n);
    for(int i=1;i<=m;i++) {
        int opt,x,y,z;
        scanf("%d",&opt);
        if(opt==1) {scanf("%d%d%d",&x,&y,&z);route_change(x,y,z);}
        if(opt==2) {scanf("%d%d",&x,&y);printf("%d\n",route_ask(x,y));}
        if(opt==3) {scanf("%d%d",&x,&z);tree_add(x,z);}
        if(opt==4) {scanf("%d",&x);printf("%d\n",tree_ask(x));}
    return 0;
}
2021/9/6 20:25
加载中...