zoukankan      html  css  js  c++  java
  • 洛谷 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

  • 相关阅读:
    3.1《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——下载文件
    rem实现手机页面自动缩放
    Git 常用命令
    使用 canvas+JS绘制钟表
    JS 操作数组的方法
    Node.js Request方法
    兼容浏览器的点击事件
    ES6知识点
    上传项目到github上
    JavaScript 编码风格
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10346916.html
Copyright © 2011-2022 走看看