首页 > 其他分享 >题解 LGP4211【[LNOI2014]LCA】

题解 LGP4211【[LNOI2014]LCA】

时间:2022-11-23 20:57:19浏览次数:35  
标签:10 LGP4211 int 题解 void LNOI2014 cnt son sum

problem

一棵树,多次给定 \(l,r,z\) 询问 \(\sum_{l\leq i\leq r}dep_{lca(i,z)}\),允许离线,\(n\leq 50000\)。

solution

转换:这个 \(dep_u\) 的定义为 \(u\) 到根节点的点数。

如果我们对于每个 \(l\leq i\leq r\),都给 \(1\leftrightarrow i\) 这条链加一,那么直接询问 \(1\leftrightarrow z\) 上的点权之和就可以了。

考虑到 \([l,r]\) 的答案可以差分成 \([1,l-1]\) 和 \([1,r]\) 的答案,直接扫描线即可。

code

点击查看代码
#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <functional>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr,##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
const int P=201314;
void red(LL&x){x=(x%P+P)%P;}
template<class T> struct Ans{
	int len; T sum;
	Ans(int len=1,T sum=0):len(len),sum(sum%P){}
	Ans operator+(Ans b){return Ans(len+b.len,sum+b.sum);}
	Ans operator+=(int k){return red(sum+=1ll*k*len),*this;}
};
template<int N,class T,class A> struct segtree{
	T tag[N<<2]; A ans[N<<2];
	segtree(){build();}
	void build(int p=1,int l=1,int r=N){
		if(l==r) return ; int mid=(l+r)>>1;
		build(p<<1,l,mid),build(p<<1|1,mid+1,r);
		ans[p]=ans[p<<1]+ans[p<<1|1];
	}
	void add(T k,int p){tag[p]+=k,ans[p]+=k;}
	void pushdown(int p){add(tag[p],p<<1),add(tag[p],p<<1|1),tag[p]=0;}
	void modify(int L,int R,int k,int p=1,int l=1,int r=N){
		if(L<=l&&r<=R) return add(k,p);
		int mid=(l+r)>>1; pushdown(p);
		if(L<=mid) modify(L,R,k,p<<1,l,mid);
		if(mid<R) modify(L,R,k,p<<1|1,mid+1,r);
		ans[p]=ans[p<<1]+ans[p<<1|1]; 
	}
	A query(int L,int R,int p=1,int l=1,int r=N){
		if(L<=l&&r<=R) return ans[p];
		int mid=(l+r)>>1; A res=A(0,0); pushdown(p);
		if(L<=mid) res=query(L,R,p<<1,l,mid);
		if(mid<R) res=res+query(L,R,p<<1|1,mid+1,r);
		return res;
	}
};
template<int N,int M,class T=int> struct graph{
	int head[N+10],nxt[M*2+10],cnt;
	struct edge{
		int u,v; T w;
		edge(int u=0,int v=0,T w=0):u(u),v(v),w(w){}
	} e[M*2+10];
	edge& operator[](int i){return e[i];}
	graph(){memset(head,cnt=0,sizeof head);}
	void add(int u,int v,int w=0){e[++cnt]=edge(u,v,w),nxt[cnt]=head[u],head[u]=cnt;}
	void link(int u,int v,int w=0){add(u,v,w),add(v,u,w);}
};
template<int N,int M,class T=int> struct treecut:public graph<N,M,T>{
	graph<N,M,T>&g=*this;
	int fa[N+10],siz[N+10],son[N+10],dep[N+10],
		dfn[N+10],top[N+10],rnk[N+10],cnt;
	treecut():cnt(0){memset(son,siz[0]=0,sizeof son);}
	void dfs(int u,int f=0){
		dep[u]=dep[fa[u]=f]+1,siz[u]=1;
		for(int i=g.head[u];i;i=g.nxt[i]){
			int v=g[i].v; if(v==fa[u]) continue;
			dfs(v,u),siz[u]+=siz[v];
			if(siz[v]>siz[son[u]]) son[u]=v;
		}
	}
	void cut(int u,int topf){
		top[rnk[dfn[u]=++cnt]=u]=topf;
		if(son[u]) cut(son[u],topf);
		for(int i=g.head[u];i;i=g.nxt[i]){
			int v=g[i].v; if(v==fa[u]||v==son[u]) continue;
			cut(v,v);
		} 
	}
	void split(int u,int v,function<void(int,int)> op){
		for(;top[u]!=top[v];u=fa[top[u]]){
			if(dep[top[u]]<dep[top[v]]) swap(u,v);
			op(dfn[top[u]],dfn[u]);
		}
		if(dep[u]<dep[v]) swap(u,v);
		op(dfn[v],dfn[u]);
	}
};
struct ask{
	int pos,w,id,u;
	ask(int pos=0,int w=0,int id=0,int u=0):pos(pos),w(w),id(id),u(u){}
	bool operator<(ask b){return pos<b.pos;}
};
int n,m,cnt;
LL ret[50010];
ask q[100010];
treecut<50010,50010> g;
segtree<50010,int,Ans<LL>> t;
int main(){
//	#ifdef LOCAL
//	 	freopen("input.in","r",stdin);
//	#endif
	scanf("%d%*d",&n);
	for(int i=2,f;i<=n;i++) scanf("%d",&f),g.link(i,f+1);
	g.dfs(1),g.cut(1,1);
	for(int l,r,z;~scanf("%d%d%d",&l,&r,&z);){
		cnt++,z++,l++,r++;
		if(l>1) q[++m]=ask(l-1,-1,cnt,z);
		q[++m]=ask(r,1,cnt,z);
	}
	sort(q+1,q+m+1);
	for(int i=1,now=1;i<=n;i++){
		g.split(i,1,[&](int l,int r){
			assert(1<=l&&l<=r&&r<=n);
//			debug("modify(dfn)(%d,%d)\n",l,r);
			t.modify(l,r,1);
		});
		for(;now<=m&&q[now].pos==i;now++){
			g.split(q[now].u,1,[&](int l,int r){
				assert(1<=l&&l<=r&&r<=n);
//				debug("query(dfn)(%d,%d)\n",l,r);
				red(ret[q[now].id]+=t.query(l,r).sum*q[now].w);
			});
		}
	}
	for(int i=1;i<=cnt;i++) printf("%lld\n",ret[i]);
	return 0;
}

标签:10,LGP4211,int,题解,void,LNOI2014,cnt,son,sum
From: https://www.cnblogs.com/caijianhong/p/solution-P4211.html

相关文章

  • ABap smartforms 预览重叠问题解决
     smartfoms在预览时总会出现文字重叠的现象,但是实际打印却又正常。如下图。 通过对sap源码的修改可以修正此问题。如下显示就正常了。......
  • P4464 [国家集训队] JZPKIL 题解
    NOIP前三天,感觉绝对复习不完了的gtm1514认为已经没有什么好害怕的了,于是做起了数学题。因为摆了大烂所以只有一道。P4464[国家集训队]JZPKIL题意不再赘述。下午看......
  • CF1392H ZS Shuffles Cards 题解
    linkDescription有\(n\)张数字牌以及\(m\)张鬼牌,有一个不可重集合\(S\),初始为空。不断执行以下操作:抽出一张牌,如果为数字牌,则加入\(S\)并移除。如果为鬼牌,如果......
  • Public NOIP Round #3(Div. 1) 题解
    T2:先判\(1,n\)有连边的情况,也就是说明最短路一定是\(1\)直接走到\(n\)。特判掉\(k=1,n=2\)的情况,这是无解的。那么如果\(k\ge2\)就令\(1,n\)都为\(U\),其余随......
  • Codeforces Round #835 (Div. 4) A-G完全题解
    比赛链接A、点击查看代码#include<bits/stdc++.h>usingnamespacestd;intmain(){intT;cin>>T;while(T--){vector<int>G;for(inti=1;......
  • 【MSSQL】SQL SERVER导入中文乱码问题解决
    公司最近承接了一个项目,甲方现使用旧版SiteServer框架(以下简称“SiteCMS”)作为门户网站,使用的数据源是SQLServer。现在需要对SiteCMS进行升级,在升级时数据库和数据库结构也......
  • 题解 LGP7888【「MCOI-06」Distinct Subsequences】
    problem给定一个由小写字符构成的字符串\(S\)。令一个字符串的价值为该串的本质不同非空子序列个数,其中子序列可以为整体。求\(S\)所有子序列的价值和。答案对\(10^......
  • Codeforces Round #790 (Div.4) A-H2题解
    原题链接:https://codeforces.com/contest/1676A.Lucky?题意:给定长度为6由数字组成的字符串问前三个数字的和是否等后三个数字的和。题解:直接相加比较即可。#include<......
  • 题解 LGP2607【[ZJOI2008] 骑士】
    problem基环树森林带权最大独立集。\(n\leq10^6\)。solution0这里先解释一下基环树森林,它就是一个\(n\)个点\(n\)条边的森林,同时是一个荒漠。我们拿出其中一棵连......
  • Codeforces Round #835 (Div.4) A-G题解
    原题链接:https://codeforces.com/contest/1744A.MediumNumber题意:给定三个数,求中间那个数(倒数第二小or倒数第二大)。题解:直接用数组存,sort一下输出中间的数即可。#in......