• 【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA


    引用题解:

    http://blog.csdn.net/popoqqq/article/details/38823457

    题目大意:

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    这题看见了直接卡壳。。。然后看了题解才搞懂要怎么写。。。

    直接复制gconeice的题解吧 

    显然,暴力求解的复杂度是无法承受的。
    考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。

    写的很详细,我就不累述了

    同样是14年的省选,同样是树链剖分,为啥辽宁省的就如此牛B,吉林省的就是水题。。。差距好大0.0

    取模的话数字不是很大 可以开long long 最后取一下模就好了 中途不要取模 弄成负的WA了我一下午0.0 又一下午0.0 又一下午0.0 啊啊啊啊啊啊啊啊啊

    ——PoPoQQQ

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 50001
    #define lson rt<<1,l,m
    #define rson rt<<1|1,m+1,r
    struct ASK{int p,z,id;}Q[N<<1];
    int n,m;
    bool operator < (const ASK &a,const ASK &b){return a.p<b.p;}
    int sumv[N<<2],delta[N<<2];
    void pushdown(int rt,int sz)
    {
    	if(delta[rt])
    	  {
    	  	sumv[rt<<1]+=(sz-(sz>>1))*delta[rt];
    	  	sumv[rt<<1|1]+=(sz>>1)*delta[rt];
    	  	delta[rt<<1]+=delta[rt];
    	  	delta[rt<<1|1]+=delta[rt];
    	  	delta[rt]=0;
    	  }
    }
    void update(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	  {
    	  	sumv[rt]+=(r-l+1);
    	  	++delta[rt];
    	  	return;
    	  }
    	pushdown(rt,r-l+1);
    	int m=(l+r>>1);
    	if(ql<=m) update(ql,qr,lson);
    	if(m<qr) update(ql,qr,rson);
    	sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
    }
    int query(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr) return sumv[rt];
    	pushdown(rt,r-l+1);
    	int m=(l+r>>1),res=0;
    	if(ql<=m) res+=query(ql,qr,lson);
    	if(m<qr) res+=query(ql,qr,rson);
    	return res;
    }
    int v[N],en,first[N],next[N];
    void AddEdge(int U,int V)
    {
    	v[++en]=V;
    	next[en]=first[U];
    	first[U]=en;
    }
    int top[N],tot,Num[N],fa[N],siz[N],son[N];
    void dfs(int U)
    {
    	siz[U]=1;
    	for(int i=first[U];i;i=next[i])
    	  {
    	    dfs(v[i]);
    	    siz[U]+=siz[v[i]];
    	    if(siz[v[i]]>siz[son[U]])
    	      son[U]=v[i];
    	  }
    }
    void df2(int U)
    {
    	Num[U]=++tot;
    	if(son[U])
    	  {
    	  	top[son[U]]=top[U];
    	  	df2(son[U]);
    	  }
    	for(int i=first[U];i;i=next[i])
    	  if(v[i]!=son[U])
    	    {
    	      top[v[i]]=v[i];
    	      df2(v[i]);
    	    }
    }
    void Update(int U)
    {
    	while(top[U]!=1)
    	  {
    	  	update(Num[top[U]],Num[U],1,1,n);
    	  	U=fa[top[U]];
    	  }
    	update(1,Num[U],1,1,n);
    }
    int Query(int U)
    {
    	int res=0;
    	while(top[U]!=1)
    	  {
    	  	res+=query(Num[top[U]],Num[U],1,1,n);
    	  	U=fa[top[U]];
    	  }
    	return res+query(1,Num[U],1,1,n);
    }
    int pre[N],ans[N];
    int main()
    {
    	int x;
    	scanf("%d%d",&n,&m);
    	for(int i=2;i<=n;++i)
    	  {
    	  	scanf("%d",&x);
    	  	AddEdge(x+1,i);
    	  	fa[i]=x+1;
    	  }
    	top[1]=1;
    	dfs(1);
    	df2(1);
    	for(int i=1;i<=m;++i)
    	  {
    	  	scanf("%d%d%d",&Q[(i<<1)-1].p,&Q[i<<1].p,&Q[(i<<1)-1].z);
    	  	++Q[(i<<1)-1].z;
    	  	++Q[i<<1].p;
    	  	Q[(i<<1)-1].id=(i<<1)-1;
    	  	Q[i<<1].z=Q[(i<<1)-1].z;
    	  	Q[i<<1].id=(i<<1);
    	  }
    	sort(Q+1,Q+(m<<1|1));
    	for(int i=1;i<=(m<<1);++i)
    	  {
    	  	for(int j=Q[i-1].p+1;j<=Q[i].p;++j)
    	  	  Update(j);
    	  	if(!(Q[i].id&1)) ans[Q[i].id>>1]=Query(Q[i].z)-pre[Q[i].id>>1];
    	  	else pre[(Q[i].id+1)>>1]=Query(Q[i].z);
    	  }
    	for(int i=1;i<=m;++i)
    	  printf("%d
    ",ans[i]%201314);
    	return 0;
    

     

  • 相关阅读:
    Xshell初步设置
    【R shiny】一些应用记录
    R shiny 小工具Windows本地打包部署
    生信工程师如何写一个小工具?
    Android 照片墙应用实现,再多的图片也不怕崩溃
    Android 高效加载大图、多图解决方案,有效避免程序OOM
    SparseArray 详解
    ActivityThread
    Activity 启动模式详解 (activity 加载模式)
    Activity 生命周期
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4346165.html
Copyright © 2020-2023  润新知