首页 > 其他分享 >[LNOI2014] LCA 树链剖分+离线处理+lca转化

[LNOI2014] LCA 树链剖分+离线处理+lca转化

时间:2023-03-29 22:22:07浏览次数:60  
标签:剖分 int ll 离线 ++ maxn lca id

困困的开始了我的修炼树剖之旅途

考虑怎么搞这个lca

是说,习惯了倍增求lca,突然冒出这么一个东西还真不会搞

那要么能一次性求很多个lca(?),要么把deep[lca(i,z)]这个东西转化一下

当我们不会倍增求lca的时候,有一个很朴素的想法就是把x到根节点一路上的点都染色

然后让y节点开始往上跳,遇到的第一个染色点就是lca

类似的,如果把x到根节点上的所有点加1,再求一遍y到根节点上的所有点的和

树上的区间加和求和都可以树剖(logn)做

那询问怎么处理?

观察到[l,r]的答案具有可加性,那么也可以差分了

把每个询问拆成两个,一个是{l-1,i,z,-1},另一个是{r,i,z,1}

按端点sort一下,从1号点开始加到n号点,顺便求个和

    l++,r++,z++;
        Q[i*2-1]=(Query){l-1,i,z,-1};
        Q[i*2]=(Query){r,i,z,1};
    }
    sort(Q+1,Q+2*m+1,cmp);
    int at=0;
    for(int i=1;i<=2*m;i++){
        while(at<Q[i].r) addpath(1,++at,1);
        ans[Q[i].id]+=Q[i].sign*qpath(1,Q[i].x);      
    }

有笨蛋处理输入的时候l++,r++,但是z没有++,是谁我不说(

 

#include<bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int maxn=2*int(1e5)+7;
ll cnt=0,ecnt=0;
ll n,m,R,id[maxn],wt[maxn],top[maxn],son[maxn],head[maxn],fa[maxn],siz[maxn],dep[maxn];
ll mod,a[maxn<<2],lazy[maxn<<2],w[maxn];
struct lys{
    int from,to,nex;
}e[maxn*2];
void addedge(int from,int to){
    ecnt++;e[ecnt].from=from;e[ecnt].to=to;e[ecnt].nex=head[from];head[from]=ecnt;
}
void dfs1(int u,int f){
    siz[u]=1;
    fa[u]=f;
    dep[u]=dep[f]+1;
    int maxson=-1;
    for(int i=head[u];i;i=e[i].nex){
        int to=e[i].to;
        if(to==f) continue;
        dfs1(to,u);
        siz[u]+=siz[to];
        if(siz[to]>maxson) son[u]=to,maxson=siz[to];
    }
}
void dfs2(int u,int topf){
    cnt++;// dfs order
    id[u]=cnt;
    wt[cnt]=w[u];
    top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u];i;i=e[i].nex){
        int to=e[i].to;
        if(to==son[u]||to==fa[u]) continue;
        dfs2(to,to);
    }
}
void build(int rt,int l,int r){
    if(l==r){
        a[rt]=0;return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    a[rt]=a[rt<<1]+a[rt<<1|1];
}
void pushdown(int rt,int l,int r){
   if(lazy[rt]){
        int mid=(l+r)>>1;
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        a[rt<<1]+=lazy[rt]*(mid-l+1);
        a[rt<<1|1]+=lazy[rt]*(r-mid);
     lazy[rt]=0;
   }    
}
void add(int rt,int l,int r,int ql,int qr,ll k){
    if(ql<=l&&r<=qr){
        a[rt]+=(r-l+1)*k;
        lazy[rt]+=k;
        return;
    }
    int mid=(l+r)>>1;
    if(lazy[rt]) pushdown(rt,l,r);
    if(ql<=mid) add(rt<<1,l,mid,ql,qr,k);
    if(mid<qr) add(rt<<1|1,mid+1,r,ql,qr,k); 
    a[rt]=a[rt<<1]+a[rt<<1|1];
}
void addpath(int x,int y,ll k){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        add(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    add(1,1,n,id[x],id[y],k);
}
ll query(int rt,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        return a[rt];
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    ll ans=0;
    if(mid>=ql) ans+=query(rt<<1,l,mid,ql,qr);
    if(mid<qr) ans+=query(rt<<1|1,mid+1,r,ql,qr); 
    return ans; 
}
ll qpath(int x,int y){
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=query(1,1,n,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=query(1,1,n,id[x],id[y]);
    return ans;
}
void addson(int u,ll k){
    add(1,1,n,id[u],id[u]+siz[u]-1,k);
}
ll qson(int u){ 
    return query(1,1,n,id[u],id[u]+siz[u]-1);
}
struct Query{
    int r,id,x,sign;
}Q[maxn*2];
bool cmp(Query a,Query b){
    return a.r<b.r;
}
ll ans[maxn];
int main(){
  //freopen("lys.in","r",stdin);
    fastio;
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        int father;cin>>father;
        father++;addedge(father,i);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int l,r,z;
        cin>>l>>r>>z;
        l++,r++,z++;
        Q[i*2-1]=(Query){l-1,i,z,-1};
        Q[i*2]=(Query){r,i,z,1};
    }
    sort(Q+1,Q+2*m+1,cmp);
    int at=0;
    for(int i=1;i<=2*m;i++){
        while(at<Q[i].r) addpath(1,++at,1);
        ans[Q[i].id]+=Q[i].sign*qpath(1,Q[i].x);      
    }
    for(int i=1;i<=m;i++) 
        cout<<ans[i]%201314<<endl;
}

 

标签:剖分,int,ll,离线,++,maxn,lca,id
From: https://www.cnblogs.com/liyishui2003/p/17270669.html

相关文章

  • oracle 离线分析其他库的归档日志
    oracle数据库是可以离线分析其他库的归档日志的,比如想分析生产库的归档日志,可以将其拿到测试库上来分析,以免影响生产库的性能。dictory模式:将数据库的数据字典抽取到操作......
  • 大数据 离线批计算 实时流量
     https://www.51doit.com/archives/1166.html  ......
  • centos 离线安装supervisor
    1、安装setuptools工具地址:https://pypi.org/project/setuptools/41.1.0/#files将安装上传到服务器解压unzipsetuptools-41.1.0.zip移动到/usr/localmvsetuptools-......
  • oh-my-zsh 离线安装配置
    1,首先需要安装git和zshyuminstall-ygitzsh2.下载离线安装包暂时先空着。3.解压安装包tar-xvfoh-my-zsh.tar4.安装和配置4.1首先切换到zsh$cdoh......
  • 长链剖分总结
    长链剖分总结长链剖分,顾名思义,就是按照链长(即深度)把树剖成若干条链。具体的,定义每个点的儿子中,子树深度最大的点是重儿子,不断跳重儿子形成的链也就是重链。长链剖分的性......
  • pip 将第三方库,变成离线包
    参考文档:https://zhuanlan.zhihu.com/p/351494670下载pipdownload-d./pathpyinstaller-ihttps://pypi.mirrors.ustc.edu.cn/simple/<-d./path>的意思是将下载的......
  • ubuntu18.04离线 安装jdk8环境
    Jdkoracle官方下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html解压tar-zxvfjdk-8u152-linux-x64.tar.gz习惯上会......
  • 【hdu6547】Tree(树链剖分, 线段树区间根号)
    problemalgorihtm1、树链剖分什么是树链剖分(重链剖分)?树链,就是树上的路径。剖分,就是把路径分类为重链和轻链。对于树上的一个点,与其相连的边中,连向的节点子树大小最大(重儿子)......
  • Wordbook:一个 GNOME 桌面的离线词典应用
    遇见Wordbook:一个GNOME桌面的离线词典应用。我们大多在谷歌、DDG或其他搜索引擎上搜索单词信息,如含义、同义词、反义词等。由于今天几乎每个人都有一个连接互......
  • [学习笔记] 树链剖分
    树链剖分的用处使用树剖将整棵树剖分为若干条链,组成线性结构,可以方便用其他的数据结构维护信息。一些定义重儿子:该节点的所有子节点中子树大小最大的点。轻儿子:该节点......