View on GitHub

Wenchong Huang

旧博客,文章搬迁完后删除

返回首页 返回专题

【LNOI2014】LCA 题解

上午拿这题做了一下NOIP模拟赛(TM确定这是NOIP难度???),然后我当即想起了昨晚做的[HNOI2015]开店,用我做那题的思路来搞这题,这题简直就是完全弱化版。然而机房一个大佬真的写了三个小时的可持久化树剖,还是没做出来,默哀三秒钟……其实我也想就把昨天代码搬上去的,然后发现,时间只有1s,空间只有128M,写个鬼的可持久化树剖!

这题没有强制在线,太好了,直接离线

还是考虑路径覆盖

按p=1~n的顺序将点p到根节点的路径覆盖,对于所有L=p+1的询问,答案减去目前为止u到根节点的覆盖长度,对于所有R=p的询问,答案加上到目前为止u到根节点的覆盖长度。然后再去覆盖下一个

就这样,AC,非常快

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define Mod 201314
#define newnode(x) x=new Node,x->lc=x->rc=null
using namespace std;

typedef long long LL;
struct Edge{int to,next;} e[300010];
int h[150010],sum=0;
struct Node
{
	Node *lc,*rc;
	int tag;LL s;
	Node(){tag=0;s=0;lc=rc=NULL;}
};
Node *rt,*null;
int top[50010],fa[50010];
int size[50010],hson[50010];
LL dis[50010];
int dfn[50010],dfs_clock=0;
vector<int> q1[50010],q2[50010];
int U[50010];
LL ans[50010];

void add_edge(int u,int v)
{
	if(u==v) return;
	sum++;
	e[sum].to=v;
	e[sum].next=h[u];
	h[u]=sum;
}

void build(Node* &o,int l,int r)
{
	newnode(o);
	if(l==r) return;
	int mid=(l+r)/2;
	build(o->lc,l,mid);
	build(o->rc,mid+1,r);
}

void modify(Node* &o,int l,int r,int nl,int nr)
{
	o->s+=nr-nl+1;
	if(l==nl&&r==nr){o->tag++;return;}
	int mid=(l+r)/2;
	if(nl>mid) modify(o->rc,mid+1,r,nl,nr);
	else if(nr<=mid) modify(o->lc,l,mid,nl,nr);
	else modify(o->lc,l,mid,nl,mid),modify(o->rc,mid+1,r,mid+1,nr);
}

LL query(Node *o,int l,int r,int nl,int nr)
{
	if(l==nl&&r==nr) return o->s;
	LL res=(LL)(nr-nl+1)*o->tag;
	int mid=(l+r)/2;
	if(nl>mid) res+=query(o->rc,mid+1,r,nl,nr);
	else if(nr<=mid) res+=query(o->lc,l,mid,nl,nr);
	else res+=query(o->lc,l,mid,nl,mid)+query(o->rc,mid+1,r,mid+1,nr);
	return res;
}

void dfs1(int u,int la)
{
	size[u]=1;
	for(int tmp=h[u];tmp;tmp=e[tmp].next)
	{
		int v=e[tmp].to;
		if(v==la) continue;
		fa[v]=u;dis[v]=dis[u]+1;
		dfs1(v,u);size[u]+=size[v];
		if((!hson[u])||size[v]>size[hson[u]]) hson[u]=v;
	}
}

void dfs2(int u,int tp)
{
	dfn[u]=++dfs_clock;
	top[u]=tp;
	if(hson[u]) dfs2(hson[u],tp);
	for(int tmp=h[u];tmp;tmp=e[tmp].next)
	{
		int v=e[tmp].to;
		if(v==fa[u]||v==hson[u]) continue;
		dfs2(v,v);
	}
}

int main()
{
	newnode(null);
	int n,q,u,v,w,l,r;
	cin>>n>>q;
	for(int i=2;i<=n;i++)
	{
		scanf("%d",&u);u++;
		add_edge(u,i);
		add_edge(i,u);
	}
	dfs1(1,0);dfs2(1,1);
	build(rt,1,n);
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d%d",&l,&r,U+i);
		l++;r++;U[i]++;
		q1[l-1].push_back(i);
		q2[r].push_back(i);
	}
	for(int i=1;i<=n;i++)
	{
		int p=i;
		while(top[p]!=1)
		{
			modify(rt,1,n,dfn[top[p]],dfn[p]);
			p=fa[top[p]];
		}
		modify(rt,1,n,1,dfn[p]);
		for(int j=0;j<q1[i].size();j++)
		{
			p=U[q1[i][j]];
			while(top[p]!=1)
			{
				ans[q1[i][j]]-=query(rt,1,n,dfn[top[p]],dfn[p]);
				ans[q1[i][j]]%=Mod;
				p=fa[top[p]];
			}
			ans[q1[i][j]]-=query(rt,1,n,1,dfn[p]);
			ans[q1[i][j]]%=Mod;
		}
		for(int j=0;j<q2[i].size();j++)
		{
			p=U[q2[i][j]];
			while(top[p]!=1)
			{
				ans[q2[i][j]]+=query(rt,1,n,dfn[top[p]],dfn[p]);
				ans[q2[i][j]]%=Mod;
				p=fa[top[p]];
			}
			ans[q2[i][j]]+=query(rt,1,n,1,dfn[p]);
			ans[q2[i][j]]%=Mod;
		}
	}
	for(int i=1;i<=q;i++) printf("%lld\n",ans[i]);
	return 0;
}