傻逼调了一天树剖

Posted orzzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了傻逼调了一天树剖相关的知识,希望对你有一定的参考价值。

啊,,调了很久就是了。

跳链的时候跳的是top的深度大的那个,不是本身深度大的。

我是傻逼。

洛谷树剖模板。

技术分享
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
inline ll read(){
    ll f=1,r=0,c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){r=r*10+c-0;c=getchar();}
    return r*f;
}
struct Edge{
    int to,nxt;
}e[N*2];
int head[N],cnt=1;ll P;
void add(int u,int v){
    e[cnt]=(Edge){v,head[u]};
    head[u]=cnt++;
    e[cnt]=(Edge){u,head[v]};
    head[v]=cnt++;
}
int siz[N],dep[N],dad[N],son[N];
void dfs1(int u,int fa){
    siz[u]=1;dad[u]=fa;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa)continue;
        dep[v]=dep[u]+1;dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
        son[u]=v;
    }
}
int pos[N],top[N],dfn;
void dfs2(int u,int anc){
    top[u]=anc;pos[u]=++dfn;
    if(!son[u])return;
    dfs2(son[u],anc);
    for(int i=head[u];i;i=e[i].nxt)
    if(e[i].to^dad[u]&&e[i].to^son[u])
    dfs2(e[i].to,e[i].to);
}
#define ls o<<1
#define rs (o<<1)|1
#define L T[o].l
#define R T[o].r
#define M L+R>>1
struct Node{
    ll l,r,add,sum;
}T[N*4];
ll a[N],b[N];
void pushdown(int o){
    (T[ls].add+=T[o].add)%=P;
    (T[rs].add+=T[o].add)%=P;
    (T[ls].sum+=(T[ls].r-T[ls].l+1)*T[o].add)%=P;
    (T[rs].sum+=(T[rs].r-T[rs].l+1)*T[o].add)%=P;
    T[o].add=0;
}
void pullup(int o){
    (T[o].sum=T[ls].sum+T[rs].sum)%=P;
}
void build(int o,int l,int r){
    if(l==r){
        T[o]=(Node){l,r,0,a[l]};
        return;
    }
    T[o]=(Node){l,r,0,0};
    build(ls,l,l+r>>1);
    build(rs,(l+r>>1)+1,r);
    pullup(o);
}
ll val,ans,ql,qr;
void upd(int o){
    if(ql<=L&&R<=qr){
        (T[o].add+=val)%=P;
        (T[o].sum+=(R-L+1)*val)%=P;
        return;
    }
    pushdown(o);
    if(ql<=M)upd(ls);
    if(qr>M) upd(rs);
    pullup(o);
}
void qsum(int o){
    if(ql<=L&&R<=qr){
        (ans+=T[o].sum)%=P;
        return;
    }
    pushdown(o);
    if(ql<=M)qsum(ls);
    if(qr>M) qsum(rs);
}
void modify(int u,int v,ll t){
    val=t;
    while(top[u]^top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        ql=pos[top[u]],qr=pos[u];upd(1);
        u=dad[top[u]];
    }
    if(pos[u]>pos[v])swap(u,v);
    ql=pos[u],qr=pos[v];upd(1);
}
void query(int u,int v){
    ans=0;
    while(top[u]^top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        ql=pos[top[u]],qr=pos[u];qsum(1);
        u=dad[top[u]];
    }
    if(pos[u]>pos[v])swap(u,v);
    ql=pos[u],qr=pos[v];qsum(1);
    printf("%lld\n",ans%P);
}
int n,m,S;
void init(){
    n=read(),m=read(),S=read(),P=read();
    for(int i=1;i<=n;i++)b[i]=read();
    for(int i=1;i<n;i++)
    add(read(),read());
    dfs1(S,0);dfs2(S,S);
    for(int i=1;i<=n;i++)
    a[pos[i]]=b[i];
    build(1,1,n);
}
void solve(){
    while(m--){
        int opt=read();
        if(opt==1){
            int u=read(),v=read();ll t=read();
            modify(u,v,t);
        }
        else if(opt==2){
            int u=read(),v=read();
            query(u,v);
        }
        else if(opt==3){
            int u=read();
            ql=pos[u],qr=ql+siz[u]-1;
            val=read();upd(1);
        }
        else{
            int u=read();
            ans=0;
            ql=pos[u],qr=ql+siz[u]-1;
            qsum(1);
            printf("%lld\n",ans%P);
        }
    }
}
int main(){
    init();
    solve();
}
View Code

感觉150行,3KB左右,字数算不多了,打了几遍也基本记下来了。

以上是关于傻逼调了一天树剖的主要内容,如果未能解决你的问题,请参考以下文章

51nod1006simple KMP

codechef FIBTREE 码农题 线段树 树剖 标记永久化

20230424小记

day-7

HDU 1813 Escape from Tetris

poj 2777