• 洛谷 P4211 [LNOI2014]LCA 解题报告


    [LNOI2014]LCA

    题意

    给一个(n(le 50000))节点的有根树,询问(l,r,z),求(sum_{lle ile r}dep[lca(i,z)])


    一直想启发式合并...

    关于LCA的深度,有一个转换。

    比如询问((x,y))(lca)深度,可以把(x)到跟每个点染色+1,然后查询(y)到根的权值。

    这个题离线进行差分,每次加一个点染色求前缀询问即可。


    Code:

    #include <cstdio>
    #include <cctype>
    #include <vector>
    const int N=5e5+10;
    const int mod=201314;
    int read()
    {
    	int x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return x;
    }
    int n,q,ans[N];
    int head[N],to[N],Next[N],cnt;
    void add(int u,int v)
    {
    	to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int dfn[N],top[N],f[N],siz[N],ws[N],dfsclock;
    void dfs1(int now)
    {
    	siz[now]=1;
    	for(int v,i=head[now];i;i=Next[i])
    	{
    		f[v=to[i]]=now;
    		dfs1(v);
    		siz[now]+=siz[v];
    		if(siz[ws[now]]<siz[v]) ws[now]=v;
    	}
    }
    void dfs2(int now,int anc)
    {
    	top[now]=anc;
    	dfn[now]=++dfsclock;
    	if(ws[now]) dfs2(ws[now],anc);
    	for(int v,i=head[now];i;i=Next[i])
    		if(!dfn[v=to[i]])
    			dfs2(v,v);
    }
    int sum[N<<2],tag[N<<2];
    #define ls id<<1
    #define rs id<<1|1
    void pushdown(int id,int L,int R)
    {
    	if(tag[id])
    	{
    		int Mid=L+R>>1;
    		(sum[ls]+=1ll*tag[id]*(Mid+1-L))%=mod;
    		(sum[rs]+=1ll*tag[id]*(R-Mid))%=mod;
    		tag[ls]+=tag[id],tag[rs]+=tag[id];
    		tag[id]=0;
    	}
    }
    void change(int id,int L,int R,int l,int r)
    {
    	if(l==L&&r==R)
    	{
    		(sum[id]+=R+1-L)%=mod;
    		++tag[id];
    		return;
    	}
    	pushdown(id,L,R);
    	int Mid=L+R>>1;
    	if(r<=Mid) change(ls,L,Mid,l,r);
    	else if(l>Mid) change(rs,Mid+1,R,l,r);
    	else change(ls,L,Mid,l,Mid),change(rs,Mid+1,R,Mid+1,r);
    	sum[id]=sum[ls]+sum[rs];
    }
    int query(int id,int L,int R,int l,int r)
    {
    	if(l==L&&r==R) return sum[id];
    	pushdown(id,L,R);
    	int Mid=L+R>>1;
    	if(r<=Mid) return query(ls,L,Mid,l,r);
    	else if(l>Mid) return query(rs,Mid+1,R,l,r);
    	else return (query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r))%mod;
    }
    void modify(int now)
    {
    	while(top[now]!=top[1])
    	{
    		change(1,1,n,dfn[top[now]],dfn[now]);
    		now=f[top[now]];
    	}
    	change(1,1,n,1,dfn[now]);
    }
    int ask(int now)
    {
    	int ret=0;
    	while(top[now]!=top[1])
    	{
    		(ret+=query(1,1,n,dfn[top[now]],dfn[now]))%=mod;
    		now=f[top[now]];
    	}
    	(ret+=query(1,1,n,1,dfn[now]))%=mod;
    	return ret;
    }
    struct node{int id,z;}bee;
    std::vector<node> qry[N];
    int main()
    {
    	n=read(),q=read();
    	for(int i=2;i<=n;i++) add(read()+1,i);
    	dfs1(1),dfs2(1,1);
    	for(int l,r,i=1;i<=q;i++)
    	{
    		l=read()+1,r=read()+1,bee.z=read()+1,bee.id=-i;
    		qry[l-1].push_back(bee);
    		bee.id=i;
    		qry[r].push_back(bee);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		modify(i);
    		for(int j=0;j<qry[i].size();j++)
    		{
    			int id=qry[i][j].id,z=qry[i][j].z;
    			if(id>0) ans[id]+=ask(z);
    			else ans[-id]-=ask(z);
    		}
    	}
    	for(int i=1;i<=q;i++)
    		printf("%d
    ",(ans[i]+mod)%mod);
    	return 0;
    }
    

    2019.2.1

  • 相关阅读:
    paip.提升效率僵尸代码的迷思
    paip.输入法编程词库多意义条目分割 python实现.
    paip.提升效率提升绑定层次form绑定取代field绑定
    paip.提升效率调试日志系统日志参数含义python
    paip.自定义java 泛型类与泛型方法的实现总结
    paip.提升效率request自动绑定domain object
    paip.提升效率filter map reduce 的java 函数式编程实现
    paip.php 5.0 5.3 5.4 5.5 6.0的新特性总结与比较
    paip.解决中文url路径的问题图片文件不能显示
    paip.判断字符是否中文与以及判读是否是汉字uapi python java php
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10346916.html
Copyright © 2020-2023  润新知