18pts,AC1、2,求调

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

STARSczy @ 2023-09-12 23:02:39

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+10;
inline int read(){
    int c,w=0,n=0;
    while((c=getchar())<'0'||'9'<c) w=c=='-';
    do n=n*10+c-'0';while('0'<=(c=getchar())&&c<='9');
    return w?-n:n;
}
inline int write(int n){
    if(n<0) putchar('-'),n=-n;
    if(n>9) write(n/10);
    putchar(n%10+'0');
    return n;
}

int n=read(),m=read(),root=read(),mod=read(),top,a[maxn]; 
struct tree{
    struct node{int l,r,data,lazy;}a[maxn<<2];
    void init(int id,int l,int r,int *p){
        a[id].l=l,a[id].r=r;
        if(l>=r){
            a[id].data=*(p+l);
            return;
        }
        int mid=(l+r)>>1;
        init(id<<1,l,mid,p);
        init(id<<1|1,mid+1,r,p);
        a[id].data=a[id<<1].data+a[id<<1|1].data;
    }
    void down(int id){
        if(!a[id].lazy) return;
        a[id].data+=a[id].lazy*(a[id].r-a[id].l+1);
        a[id<<1].lazy+=a[id].lazy;
        a[id<<1|1].lazy+=a[id].lazy;
        a[id].lazy=0;
    }
    void update(int id){
        a[id].data=
        a[id<<1].data+a[id<<1].lazy*(a[id<<1].r-a[id<<1].l+1)+
        a[id<<1|1].data+a[id<<1|1].lazy*(a[id<<1|1].r-a[id<<1|1].l+1);
    }
    void change(int id,int l,int r,int add){
        cout<<l<<","<<r<<"]";
        if(a[id].l==l&&a[id].r==r){
            a[id].lazy+=add;
            return;
        }
        down(id);
        if(a[id<<1].r<l) change(id<<1|1,l,r,add);
        else if(a[id<<1|1].l>r) change(id<<1,l,r,add);
        else{
            change(id<<1,l,a[id<<1].r,add);
            change(id<<1|1,a[id<<1|1].l,r,add);
        }
        update(id);
    }
    int sum(int id,int l,int r){
        if(a[id].l==l&&a[id].r==r){
            return a[id].data+a[id].lazy*(a[id].r-a[id].l+1);
        }
        down(id);
        if(a[id<<1|1].l>r) return sum(id<<1,l,r);
        if(a[id<<1].r<l) return sum(id<<1|1,l,r);
        return sum(id<<1,l,a[id<<1].r)+sum(id<<1|1,a[id<<1|1].l,r);
    }
}t;
struct node{int size,data,hs,dep,lt,rk,fa;set<int> son;}v[maxn];
void build(int x){
    v[x].size=1;
    if(!v[x].son.size()) return;
    int mx=0;
    for(auto it=v[x].son.begin();it!=v[x].son.end();++it){
        v[*it].son.erase(x),v[*it].dep=v[x].dep+1,v[*it].fa=x;
        build(*it),v[x].size+=v[*it].size;
        if(v[*it].size>v[mx].size) mx=*it;
    }
    v[x].hs=mx,v[x].son.erase(mx);
}
void build1(int x){
    if(!v[x].lt) v[x].lt=x;
    v[x].rk=++top,a[top]=v[x].data;
    if(v[x].hs) v[v[x].hs].lt=v[x].lt,build1(v[x].hs);
    for(auto it=v[x].son.begin();it!=v[x].son.end();++it) build1(*it);
}
void add(int a,int b,int x){
    while(v[a].lt!=v[b].lt){
        if(v[v[a].lt].dep<v[v[b].lt].dep) swap(a,b);
        t.change(1,v[a].rk,v[v[a].lt].rk,x),a=v[v[a].lt].fa;
    }
    if(v[a].rk>v[b].rk) swap(a,b);
    t.change(1,v[a].rk,v[b].rk,x);
}
int sum(int a,int b){
    int ans=0;
    while(v[a].lt!=v[b].lt){
        if(v[v[a].lt].dep<v[v[b].lt].dep) swap(a,b);
        (ans+=t.sum(1,v[a].rk,v[v[a].lt].rk))%mod,a=v[v[a].lt].fa;
    }
    if(v[a].rk>v[b].rk) swap(a,b);
    return (ans+=t.sum(1,v[a].rk,v[b].rk))%mod;
}
void addtree(int x,int a){t.change(1,v[x].rk,v[x].rk+v[x].size-1,a);}
int sumtree(int x){return t.sum(1,v[x].rk,v[x].rk+v[x].size-1);}
void dfs(int x){
    if(v[x].hs) dfs(v[x].hs);
    for(auto it=v[x].son.begin();it!=v[x].son.end();++it) dfs(*it);
}

signed main(){
    for(int i=1;i<=n;++i) v[i].data=read();
    for(int i=1;i<n;++i){
        int a=read(),b=read();
        v[a].son.insert(b),v[b].son.insert(a);
    }
    build(root);
    build1(root);
    t.init(1,1,n,a);
    while(m--) switch(read()){
        case(1):{
            int x=read(),y=read(),z=read()%mod;
            add(x,y,z);
            break;
        }
        case(2):{
            int x=read(),y=read();
            write(sum(x,y)),puts("");
            break;
        }
        case(3):{
            int x=read(),y=read()%mod;
            addtree(x,y);
            break;
        }
        case(4):{
            int x=read();
            write(sumtree(x)),puts("");
            break;
        }
    }
    return 0;
}

by _sunkuangzheng_ @ 2023-09-12 23:30:32

@stars_czy

  1. 树剖函数向上跳重链的时候,链头的 dfs 序小于节点 a,因此应该将 t.change(1,v[a].rk,v[v[a].lt].rk,x) 改成 t.change(1,v[v[a].lt].rk,v[a].rk,x),查询函数同理。
  2. 线段树查询函数里统计区间和没有取模。

改完以上两点即可 AC,如果有帮助给个关注谢谢喵 /kel


by STARSczy @ 2023-09-13 14:34:59

@sunkuangzheng 谢谢,已关注,已AC


|