• LNOI2014 LCA


    题目链接:戳我

    区间求和可以分成前缀和差分,所以我们可以把每次询问的l,r差分成([1,r]-[1,l-1])

    对于每一组询问,我们把([l,r])内的每个点到根的链上都+1,然后x和根的链上的累加和就是LCA的深度总和了。

    为什么呢?大家可以画画图,就显而易见了因为题目上说了LCA的深度为它到根结点的距离+1,那么从一个结点出发,给它到根结点的链上的节点累加1的时候,显然是从LCA开始才会对询问点产生贡献的。而这个贡献个就是从LCA开始,到根结点(包含),的点数,而这正等于题目中对LCA深度的定义。

    然后这个问题就可以转换成树上区间加和,区间求和啦!这不就是树连剖分的模板了吗,显然一个一个求出来是不现实的,所以我们要考虑一次求出来很多个。所以我们先把所有询问都离线下来,然后我们按照pos从小到大排序,然后如果now==a[i].pos的时候,就可以累加给该询问答案了。

    具体的请看代码吧 QAQ

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #define MAXN 500010
    #define mod 201314
    using namespace std;
    
    int n,Q,tt,cnt,tot;
    int wt[MAXN],bit[MAXN],id[MAXN];
    int head[MAXN<<1],fa[MAXN],topf[MAXN],dep[MAXN],top[MAXN],son[MAXN],siz[MAXN];
    
    struct Edge{int nxt,to;}edge[MAXN<<1];
    struct Node{int v,sum,l,r,tag;}t[MAXN<<4];
    struct Node2{int pos,num,flag;}a[MAXN];
    struct Que{int ans1,ans2,x;}q[MAXN];
    
    inline bool cmp(struct Node2 x,struct Node2 y){return x.pos<y.pos;}
    
    inline void add(int from,int to){edge[++tt].nxt=head[from],edge[tt].to=to,head[from]=tt;}
    
    inline void dfs1(int x,int pre)
    {
        dep[x]=dep[pre]+1;
    	siz[x]=1;
    	int maxx=-1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            dfs1(v,x);
    		siz[x]+=siz[v];
    		if(siz[v]>maxx) maxx=siz[x],son[x]=v;
        }
    }
    
    inline void dfs2(int x,int topf)
    {
        top[x]=topf;
    	id[x]=++cnt;
    	if(son[x]) dfs2(son[x],topf);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
    		if(v==fa[x]||v==son[x]) continue;
    		dfs2(v,v);
        }
    }
    
    inline int ls(int x){return x<<1;}
    
    inline int rs(int x){return x<<1|1;}
    
    inline void push_up(int x){t[x].sum=(t[ls(x)].sum+t[rs(x)].sum)%mod;}
    
    inline void f(int x,int k)
    {
    	int l=t[x].l,r=t[x].r;
    	t[x].tag=(t[x].tag+k)%mod;
    	t[x].sum=(t[x].sum+1ll*(r-l+1)*k%mod)%mod;
    }
    
    inline void push_down(int x)
    {
    	if(t[x].tag)
    	{
    		f(ls(x),t[x].tag);
    		f(rs(x),t[x].tag);
    		t[x].tag=0;
    	}
    }
    
    inline void build(int x,int l,int r)
    {
    	t[x].l=l,t[x].r=r;
    	if(l==r){t[x].sum=0;return;}
    	int mid=(l+r)>>1;
    	build(ls(x),l,mid);
    	build(rs(x),mid+1,r);
    	push_up(x);
    }
    
    inline void update(int x,int ll,int rr,int k)
    {
    	int l=t[x].l,r=t[x].r;
    	if(ll<=l&&r<=rr) 
    	{
    		f(x,k);
    		return;
    	}
    	int mid=(l+r)>>1;
    	push_down(x);
    	if(ll<=mid) update(ls(x),ll,rr,k);
    	if(mid<rr) update(rs(x),ll,rr,k);
    	push_up(x);
    }
    
    inline int query(int x,int ll,int rr)
    {
    	int l=t[x].l,r=t[x].r;
    	if(ll<=l&&r<=rr) return t[x].sum;
    	int mid=(l+r)>>1;
    	push_down(x);
    	int cur_ans=0;
    	if(ll<=mid) cur_ans+=query(ls(x),ll,rr);
    	if(mid<rr) cur_ans+=query(rs(x),ll,rr);
    	return cur_ans;
    }
    
    inline void ADD(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		update(1,id[top[x]],id[x],1);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	update(1,id[x],id[y],1);
    }
    
    inline int QUERY(int x,int y)
    {
    	int cur_ans=0;
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		cur_ans=(cur_ans+query(1,id[top[x]],id[x]))%mod;
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	cur_ans=(cur_ans+query(1,id[x],id[y]))%mod;
    	return cur_ans;
    }
    
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&Q);
    	n--;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&fa[i]);
    		add(fa[i],i);
    	}
    	
    	for(int i=1;i<=Q;i++)
    	{
    		int l,r;
    		scanf("%d%d%d",&l,&r,&q[i].x);
    		a[++tot].pos=l-1,a[tot].num=i,a[tot].flag=0;
    		a[++tot].pos=r,a[tot].num=i,a[tot].flag=1;
    	}
    	build(1,1,n+1);
    	dfs1(0,0);
    	dfs2(0,0);
    	// for(int i=0;i<=n;i++) printf("fa[%d]=%d
    ",i,fa[i]); puts("");
    	// for(int i=0;i<=n;i++) printf("dep[%d]=%d
    ",i,dep[i]); puts("");
    	// for(int i=0;i<=n;i++) printf("son[%d]=%d
    ",i,son[i]); puts("");
    	// for(int i=0;i<=n;i++) printf("siz[%d]=%d
    ",i,siz[i]); puts("");
    	// for(int i=0;i<=n;i++) printf("top[%d]=%d
    ",i,top[i]); puts("");
    	// for(int i=0;i<=n;i++) printf("id[%d]=%d
    ",i,id[i]);
    	int now=-1;
    	sort(&a[1],&a[tot+1],cmp);
    	for(int i=1;i<=tot;i++)
    	{ 
    		while(a[i].pos>now)
    		{
    			now++;
    			ADD(now,0);
    		}
    		int maomao=a[i].num;
    		if(a[i].flag==0) q[maomao].ans1=QUERY(q[maomao].x,0);
    		if(a[i].flag==1) q[maomao].ans2=QUERY(q[maomao].x,0);
    	}
    	for(int i=1;i<=Q;i++)
    		printf("%d
    ",((q[i].ans2-q[i].ans1)%mod+mod)%mod);
        return 0;
    }
    
  • 相关阅读:
    JSON的一个例子(代码来源于网上)
    浅谈Event Flow、Process、Method及其Applications
    JS中object与constructor的分析
    浅谈for...in与for....of
    浅谈语言的过去与未来
    正则表达式的四个小应用
    初步了解DOM与BOM
    String Method的字符串变换的一个例子
    update 批量更新
    一个 Tomcat下两个项目。
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10774514.html
Copyright © 2020-2023  润新知