ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

(多校)校门外歪脖树上的鸽子

2021-11-06 15:34:58  阅读:193  来源: 互联网

标签:树上 鸽子 int lim top 多校 dat dep now


先观察题目性质

考虑形式化满足哪些条件的点被选( update / query )

我们观察一张图:

image

对于上图区间 \([3,10]\),选的的点依次为:\(14,5,6,7,8,17\)

其实就是我们把 \(l~r\) 点的树上路径拿下来

根据 \(lca\) 把树分为两部分

我们把左链和右链分开考虑

对于左链:

先对于节点 \(l\) ,我们找到 \(l\) 一直向右上跳的最远位置(设其为 \(a\))

如果这个点不是 \(lca\) 【 我们需要对于是否会直接跳到 \(lca\) 分开考虑 】

那 \(a\) 就是其中一个被选点

对于 \(fa[a] - lca\) 这条链如果某节点为左儿子

那么他的兄弟节点就为被选点

( 右链反之 ) ( 询问与更改对应 )

Code
#include <bits/stdc++.h>
#define re register
#define int long long
// #define ll long long
// #define lls long long
#define pir make_pair
#define fr first 
#define sc second
#define db double
using namespace std;
const int mol=993244853;
const int maxn=5e5+10;
const int INF=1e9+10;
inline int qpow(int a,int b) { int ans=1; while(b) { if(b&1) (ans*=a)%=mol; (a*=a)%=mol; b>>=1; } return (ans+mol)%mol; }
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w;
}

int n,m,root,w[maxn]; bool isl[maxn],isr[maxn]; int backl[maxn],backr[maxn],bro[maxn];
struct DATE { int l,r,ll,rr; } dat[maxn];
struct STG {
    #define lid (id<<1)
    #define rid (id<<1|1)
    struct TREE { int sum,ks,lazy; } tre[maxn<<2]; int w[maxn]; 
    inline void build(int id,int l,int r) {
        if(l==r) { tre[id].ks=w[l]; return ; }
        int mid=(l+r)>>1;
        build(lid,l,mid); build(rid,mid+1,r);
        tre[id].ks=tre[lid].ks+tre[rid].ks;
    }
    inline void push_down(int id) {  
        int s=tre[id].lazy; tre[id].lazy=0;
        tre[lid].lazy+=s; tre[rid].lazy+=s;
        tre[lid].sum+=tre[lid].ks*s; tre[rid].sum+=tre[rid].ks*s;
    }
    inline void ins(int id,int l,int r,int ll,int rr,int val) {
        if(ll<=l&&r<=rr) { tre[id].lazy+=val; tre[id].sum+=val*tre[id].ks; return ; }
        if(tre[id].lazy) push_down(id);
        int mid=(l+r)>>1;
        if(ll<=mid) ins(lid,l,mid,ll,rr,val); 
        if(rr>mid) ins(rid,mid+1,r,ll,rr,val);
        tre[id].sum=tre[lid].sum+tre[rid].sum;
    }
    inline int quy(int id,int l,int r,int ll,int rr) {
        if(ll<=l&&r<=rr) { return tre[id].sum; }
        if(tre[id].lazy) push_down(id);
        int mid=(l+r)>>1,ans=0;
        if(ll<=mid) ans+=quy(lid,l,mid,ll,rr);
        if(rr>mid) ans+=quy(rid,mid+1,r,ll,rr);
        return ans;
    }
} trel,trer;
int size[maxn],son[maxn],dep[maxn],fa[maxn];
int tot,dfn[maxn],top[maxn],eid[maxn];
inline void dfs1(int now) {
    size[now]=1; dep[now]=dep[fa[now]]+1;
    if(!backl[now]) backl[now]=now;
    if(!backr[now]) backr[now]=now;
    
    if(!dat[now].l&&!dat[now].r) { dat[now].ll=dat[now].rr=now; return ; }
    
    backr[dat[now].l]=backr[now]; dfs1(dat[now].l); size[now]+=size[dat[now].l];
    backl[dat[now].r]=backl[now]; dfs1(dat[now].r); size[now]+=size[dat[now].r];
    son[now]=size[dat[now].l]>size[dat[now].r]? dat[now].l:dat[now].r;
    
    w[dat[now].l]=(dat[dat[now].r].rr-dat[dat[now].r].ll+1);
    w[dat[now].r]=(dat[dat[now].l].rr-dat[dat[now].l].ll+1);
    
    dat[now].ll=dat[dat[now].l].ll;
    dat[now].rr=dat[dat[now].r].rr;

}

inline void dfs2(int now,int pre) {
    dfn[now]=++tot; eid[tot]=now; top[now]=pre;
    if(son[now]) dfs2(son[now],pre); else return ;
    if(dat[now].l!=son[now]) {
        dfs2(dat[now].l,dat[now].l);
    } 
    if(dat[now].r!=son[now]) {
        dfs2(dat[now].r,dat[now].r);
    }
}

inline int getlca(int a,int b) {
    while(top[a]!=top[b]) {
        if(dep[top[a]]<dep[top[b]]) swap(a,b);
        a=fa[top[a]];
    }
    return dep[a]<dep[b]? a:b;
}

inline void wor(int a,int b,int d) {
    int lca=getlca(a,b);
    if(dep[backr[a]]<=dep[lca]&&dep[backl[b]]<=dep[lca]) { 
        if(lca==root) w[lca]+=(dat[lca].rr-dat[lca].ll+1)*d; 
        else if(isl[lca]) { trer.ins(1,1,tot,dfn[bro[lca]],dfn[bro[lca]],d); }
        else if(isr[lca]) { trel.ins(1,1,tot,dfn[bro[lca]],dfn[bro[lca]],d); }
        return ; 
    }
    if(dep[backr[a]]<=dep[lca]) {
        a=dat[lca].l;
        if(isl[a]) { trer.ins(1,1,tot,dfn[bro[a]],dfn[bro[a]],d); }
        else if(isr[a]) { trel.ins(1,1,tot,dfn[bro[a]],dfn[bro[a]],d); }
    } else {
        a=backr[a];
        if(isl[a]) { trer.ins(1,1,tot,dfn[bro[a]],dfn[bro[a]],d); }
        else if(isr[a]) { trel.ins(1,1,tot,dfn[bro[a]],dfn[bro[a]],d); }
        a=fa[a]; int lim=dat[lca].l;
        if(dep[a]>dep[lim]) {
            while(dep[top[a]]>dep[lim]) {
                trel.ins(1,1,tot,dfn[top[a]],dfn[a],d); a=fa[top[a]];
            }
            if(dep[a]>dep[lim]) {
                int ls=top[dat[lim].l]==top[a]? dat[lim].l:dat[lim].r;
                trel.ins(1,1,tot,dfn[ls],dfn[a],d);
            }
        }
    }
    if(dep[backl[b]]<=dep[lca]) {
        b=dat[lca].r;
        if(isl[b]) { trer.ins(1,1,tot,dfn[bro[b]],dfn[bro[b]],d); }
        else if(isr[b]) { trel.ins(1,1,tot,dfn[bro[b]],dfn[bro[b]],d); }
    } else {
        b=backl[b];
        if(isl[b]) { trer.ins(1,1,tot,dfn[bro[b]],dfn[bro[b]],d); }
        else if(isr[b]) { trel.ins(1,1,tot,dfn[bro[b]],dfn[bro[b]],d); }
        b=fa[b]; int lim=dat[lca].r;
        if(dep[b]>dep[lim]) {
            while(dep[top[b]]>dep[lim]) {
                trer.ins(1,1,tot,dfn[top[b]],dfn[b],d); b=fa[top[b]];
            }
            if(dep[b]>dep[lim]) {
                int ls=top[dat[lim].l]==top[b]? dat[lim].l:dat[lim].r;
                trer.ins(1,1,tot,dfn[ls],dfn[b],d);
            }
        }
    }
}

inline int qus(int a,int b) {
    int lca=getlca(a,b),ans=0;
    if(dep[backr[a]]<=dep[lca]&&dep[backl[b]]<=dep[lca]) { 
        if(lca==root) ans+=w[lca];
        else if(isl[lca]) { ans+=trer.quy(1,1,tot,dfn[bro[lca]],dfn[bro[lca]]); }
        else if(isr[lca]) { ans+=trel.quy(1,1,tot,dfn[bro[lca]],dfn[bro[lca]]); }
        return ans;
    }
    if(dep[backr[a]]<=dep[lca]) {
        a=dat[lca].l; 
        if(isl[a]) { ans+=trer.quy(1,1,tot,dfn[bro[a]],dfn[bro[a]]); }
        else if(isr[a]) { ans+=trel.quy(1,1,tot,dfn[bro[a]],dfn[bro[a]]); }
    } else {
        a=backr[a]; 
        if(isl[a]) { ans+=trer.quy(1,1,tot,dfn[bro[a]],dfn[bro[a]]); }
        else if(isr[a]) { ans+=trel.quy(1,1,tot,dfn[bro[a]],dfn[bro[a]]); }
        a=fa[a]; int lim=dat[lca].l;
        if(dep[a]>dep[lim]) {
            while(dep[top[a]]>dep[lim]) {
                ans+=trel.quy(1,1,tot,dfn[top[a]],dfn[a]); a=fa[top[a]];
            }
            if(dep[a]>dep[lim]) {
                int ls=top[dat[lim].l]==top[a]? dat[lim].l:dat[lim].r;
                ans+=trel.quy(1,1,tot,dfn[ls],dfn[a]);
            }
        }
    }
    if(dep[backl[b]]<=dep[lca]) {
        b=dat[lca].r; 
        if(isl[b]) { ans+=trer.quy(1,1,tot,dfn[bro[b]],dfn[bro[b]]); }
        else if(isr[b]) { ans+=trel.quy(1,1,tot,dfn[bro[b]],dfn[bro[b]]); }
    } else {
        b=backl[b]; 
        if(isl[b]) { ans+=trer.quy(1,1,tot,dfn[bro[b]],dfn[bro[b]]); }
        else if(isr[b]) { ans+=trel.quy(1,1,tot,dfn[bro[b]],dfn[bro[b]]); }
        b=fa[b]; int lim=dat[lca].r;
        if(dep[b]>dep[lim]) {
            while(dep[top[b]]>dep[lim]) {
                ans+=trer.quy(1,1,tot,dfn[top[b]],dfn[b]); b=fa[top[b]];
            }
            if(dep[b]>dep[lim]) {
                int ls=top[dat[lim].l]==top[b]? dat[lim].l:dat[lim].r;
                ans+=trer.quy(1,1,tot,dfn[ls],dfn[b]);
            }
        }
    }
    return ans;
}

signed main(void) {
    freopen("pigeons.in","r",stdin); freopen("pigeons.out","w",stdout);
    n=read(); m=read();
    for(re int i=1,a,b;i<n;i++) {
        dat[i+n].l=read(); dat[i+n].r=read();
        bro[dat[i+n].l]=dat[i+n].r;
        bro[dat[i+n].r]=dat[i+n].l;
        fa[dat[i+n].l]=n+i; fa[dat[i+n].r]=n+i;
        isl[dat[i+n].l]=1; isr[dat[i+n].r]=1;
    }

    for(re int i=n+1;i<2*n;i++) if(!fa[i]) { root=i; break; }
    dfs1(root); dfs2(root,root); 
    for(re int i=1;i<2*n;i++) {
        if(isl[i]) {
            trel.w[dfn[i]]=w[i];
        }
        else if(isr[i]) {
            trer.w[dfn[i]]=w[i];
        }
    }
    trel.build(1,1,tot); trer.build(1,1,tot);

    for(re int i=1,opt,l,r,d;i<=m;i++) {
        opt=read();
        if(opt==1) {
            l=read(); r=read(); d=read();
            wor(l,r,d); 
        }
        else {
            l=read(); r=read();
            printf("%lld\n",qus(l,r));
        }
    }
    return 0;
}

标签:树上,鸽子,int,lim,top,多校,dat,dep,now
来源: https://www.cnblogs.com/zjxlm/p/15517058.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有