zoukankan      html  css  js  c++  java
  • 【模板】树链剖分

    树链剖分->链加、链和、子树加、子树和

    树状数组->区间加、区间和

    链上操作是树剖最基本的操作了,剖完可以用树状数组或是线段树维护一下,子树操作只要搞出做树剖时的dfs序就可以了,剖出的链和子树都是连续的区间。

    因为9018上好像没有树剖的模板,学长就说要加,随便打了打交洛谷上居然挂了,查了好久发现写了if(i==1)i=read(),Tadd(x,i,read());if(i==2)……这种代码,1号操作中如果输入了2、3、4之类的程序就会挂……虽然之前遇到过这种问题了,但这次居然恰好过了样例QAQ。重用变量需谨慎。

    #include<cstdio>
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
        return X;
    }
    #define MN 100000
    struct edge{int nx,t;}e[MN*2+5];
    int p,a[MN+5],h[MN+5],en,fa[MN+5],s[MN+5],mx[MN+5],d[MN+5];
    int f[MN+5],l[MN+5],r[MN+5],dfn,s1[MN+5],s2[MN+5];
    void inc(int*s,int x,int z){for(;x<=MN;x+=x&-x)s[x]=(s[x]+z)%p;}
    int sum(int*s,int x){int r=0;for(;x;x-=x&-x)r=(r+s[x])%p;return r;}
    void add(int l,int r,int x)
    {
        inc(s1,l,x);inc(s1,r+1,-x);
        inc(s2,l,1ll*x*(l-1)%p);inc(s2,r+1,-1ll*x*r%p);
    }
    int query(int l,int r)
    {
        return((1ll*r*sum(s1,r)-(l-1ll)*sum(s1,l-1)-sum(s2,r)+sum(s2,l-1))%p+p)%p;
    }
    inline void ins(int x,int y)
    {
        e[++en]=(edge){h[x],y};h[x]=en;
        e[++en]=(edge){h[y],x};h[y]=en;
    }
    void pre(int x)
    {
        s[x]=1;
        for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa[x])
        {
            fa[e[i].t]=x;d[e[i].t]=d[x]+1;pre(e[i].t);
            s[x]+=s[e[i].t];if(s[e[i].t]>s[mx[x]])mx[x]=e[i].t;
        }
    }
    void dfs(int x,int k)
    {
        f[x]=k;l[x]=++dfn;add(dfn,dfn,a[x]);
        if(mx[x])dfs(mx[x],k);
        for(int i=h[x];i;i=e[i].nx)
            if(e[i].t!=fa[x]&&e[i].t!=mx[x])dfs(e[i].t,e[i].t);
        r[x]=dfn;
    }
    void Tadd(int x,int y,int z)
    {
        while(f[x]!=f[y])
            if(d[f[x]]>d[f[y]])add(l[f[x]],l[x],z),x=fa[f[x]];
            else add(l[f[y]],l[y],z),y=fa[f[y]];
        d[x]<d[y]?add(l[x],l[y],z):add(l[y],l[x],z);
    }
    int Tquery(int x,int y)
    {
        int r=0;
        while(f[x]!=f[y])
            if(d[f[x]]>d[f[y]])r=(r+query(l[f[x]],l[x]))%p,x=fa[f[x]];
            else r=(r+query(l[f[y]],l[y]))%p,y=fa[f[y]];
        return (r+(d[x]<d[y]?query(l[x],l[y]):query(l[y],l[x])))%p;
    }
    int main()
    {
        fread(B,1,1<<26,stdin);
        int n,m,rt,i,x,y;
        n=read();m=read();rt=read();p=read();
        for(i=1;i<=n;++i)a[i]=read();
        for(i=1;i<n;++i)ins(read(),read());
        pre(rt);dfs(rt,rt);
        while(m--)
        {
            i=read();x=read();
            if(i==1)y=read(),Tadd(x,y,read());
            if(i==2)printf("%d
    ",Tquery(x,read()));
            if(i==3)add(l[x],r[x],read());
            if(i==4)printf("%d
    ",query(l[x],r[x]));
        }
    }
  • 相关阅读:
    python3 TypeError: a bytes-like object is required, not 'str'
    Centos 安装Python Scrapy PhantomJS
    Linux alias
    Vim vimrc配置
    Windows下 Python Selenium PhantomJS 抓取网页并截图
    Linux sort
    Linux RSync 搭建
    SSH隧道 访问内网机
    笔记《鸟哥的Linux私房菜》7 Linux档案与目录管理
    Tornado 错误 "Global name 'memoryview' is not defined"
  • 原文地址:https://www.cnblogs.com/ditoly/p/ShuPou.html
Copyright © 2011-2022 走看看