zoukankan      html  css  js  c++  java
  • BZOJ3626 [LNOI2014]LCA

    BZOJ3626 [LNOI2014]LCA


    题目描述

    传送门

    题目分析

    可以考虑不计时间复杂度怎么做,求出所有(LCA)然后暴力求和。

    那么可以发现这个过程应该是具有可优化性。

    一次性求出所有的(LCA)显然不大现实,但是可以发现,我们可能求出的(LCA)都在根到(z)这个节点的路径上。

    可以考虑把根到(z)的路径的权(+1),这样我们的单独看每次操作就等价于求(sum_{lle ile r}sum(root->i))

    可以发现,这个操作就等价于把所有(l->r)之间的节点到根的路径都(+1)后,求出的从(z)到根节点的路径和。

    可以发现这个操作具有可加性和可减性。

    考虑离线处理问题,对所有位置的操作排序之后,利用差分求出所有询问的结果。

    可以先从0号节点开始插入,然后即时查询。

    即要求的就是(sum[r]-sum[l-1])

    可以发现需要维护的是树上的链加和链求和,可以用树链剖分维护。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid ((l+r)>>1)
    const int MAXN=1e5+7;
    const int mo=201314;
    int f[MAXN],id[MAXN],w[MAXN],at[MAXN],top[MAXN],dep[MAXN],wson[MAXN],size[MAXN],cnt,tot,add[MAXN<<2],sum[MAXN<<2],n,m;
    vector<int> edge[MAXN];
    struct Q{
    	int pos,id,fl,z;
    	bool operator <(const Q &rhs)const{
    		return pos<rhs.pos;
    	}
    }a[MAXN];
    struct Ans{
    	int l,r;
    }s[MAXN];
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void dfs(int u,int fa)
    {
    	size[u]=1;dep[u]=dep[fa]+1;f[u]=fa;
    	for(int i=0;i<edge[u].size();i++){
    		int v=edge[u][i];
    		if(v==fa) continue;
    		dfs(v,u);
    		size[u]+=size[v];
    		if(size[wson[u]]<size[v]) wson[u]=v;
    	}
    }
    inline void dfs2(int u,int tp)
    {
    	id[u]=++cnt;top[u]=tp;
    	if(wson[u]) dfs2(wson[u],tp);
    	for(int i=0;i<edge[u].size();i++){
    		int v=edge[u][i];
    		if(v==f[u]||v==wson[u]) continue;
    		dfs2(v,v);
    	}
    }
    inline void pushdown(int l,int r,int rt)
    {
    	if(add[rt]){
    		(add[ls]+=add[rt])%=mo;(add[rs]+=add[rt])%=mo;
    		(sum[ls]+=(mid-l+1)*add[rt])%=mo;(sum[rs]+=(r-mid)*add[rt])%=mo;
    		add[rt]=0;
    	}
    }
    inline void update(int L,int R,int l,int r,int rt)
    {
    	if(L<=l&&r<=R){
    		add[rt]+=1;
    		(sum[rt]+=r-l+1)%=mo;
    		return;
    	}
    	pushdown(l,r,rt);
    	if(L<=mid) update(L,R,l,mid,ls);
    	if(R>mid) update(L,R,mid+1,r,rs);
    	sum[rt]=sum[ls]+sum[rs];
    }
    inline int query(int L,int R,int l,int r,int rt)
    {
    	if(L<=l&&r<=R) return sum[rt];
    	pushdown(l,r,rt);
    	int ans=0;
    	if(L<=mid) ans+=query(L,R,l,mid,ls);
    	if(R>mid) ans+=query(L,R,mid+1,r,rs);
    	return ans;
    }
    inline void Update(int x,int y)
    {
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		update(id[top[x]],id[x],1,n,1);
    		x=f[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	update(id[x],id[y],1,n,1);
    }
    inline int Query(int x,int y)
    {
    	int ans=0;
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		(ans+=query(id[top[x]],id[x],1,n,1))%=mo;
    		x=f[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	ans+=query(id[x],id[y],1,n,1);
    	return ans%mo;
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=2;i<=n;i++){
    		int x=read()+1;
    		edge[i].push_back(x);
    		edge[x].push_back(i);
    	}
    	dfs(1,0);dfs2(1,1);
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read()+1,z=read()+1;
    		a[++tot]=(Q){x,i,0,z};
    		a[++tot]=(Q){y,i,1,z};
    	}
    	sort(a+1,a+tot+1);
    	int now=0;
    	for(int i=1;i<=tot;i++){
    		while(now<a[i].pos){now++;Update(now,1);}
    		if(!a[i].fl) s[a[i].id].l=Query(a[i].z,1);
    		else s[a[i].id].r=Query(a[i].z,1);
    	}
    	for(int i=1;i<=m;i++){
    		printf("%d
    ", ((s[i].r-s[i].l)%mo+mo)%mo);
    	}
    }
    
  • 相关阅读:
    Algebraic Data Type 及其在 Haskell 和 Scala 中的表现
    理解Rust的引用与借用
    ZooKeeper学习之路 (九)利用ZooKeeper搭建Hadoop的HA集群
    ZooKeeper学习之路 (八)ZooKeeper原理解析
    ZooKeeper学习之路 (七)ZooKeeper设计特点及典型应用场景
    ZooKeeper学习之路 (六)ZooKeeper API的简单使用(二)级联删除与创建
    ZooKeeper学习之路 (五)ZooKeeper API的简单使用 增删改查
    ZooKeeper学习之路 (四)ZooKeeper开发环境eclipse配置
    Zookeeper学习之路 (三)shell操作
    Zookeeper学习之路 (二)集群搭建
  • 原文地址:https://www.cnblogs.com/victorique/p/10242494.html
Copyright © 2011-2022 走看看