zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj3626:loj2558:p4211:[LNOI2014]LCA

    题目大意

    有一棵有(n)((nleq5*10^4))个点的树,(q)((qleq5*10^4))次询问,每次给出(l,r,x)表示询问所有编号在([l,r])的点与点(x)的LCA的深度之和

    题解

    ([l,r])里每个点和该点的所有祖先点权+1后,查询点(x)和它的祖先的点权和就行了
    可持久化线段树维护

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k])
    #define maxn 50010
    #define ls (son[u][0])
    #define rs (son[u][1])
    #define lsa son[ua][0]
    #define rsa son[ua][1]
    #define lsb son[ub][0]
    #define rsb son[ub][1]
    #define mi (l+r>>1)
    #define LL long long
    using namespace std;
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	if(x==0){putchar('0'),putchar('
    ');return;}
    	int f=0;char ch[20];
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	putchar('
    ');
    	return;
    }
    const int mod=201314;
    int n,q,rt[maxn],tr[maxn<<7],mk[maxn<<7],son[maxn<<7][2],ver[maxn<<7],fir[maxn],nxt[maxn],v[maxn],cnt,fa[maxn];
    int dfn[maxn],tim,wson[maxn],siz[maxn],top[maxn],cntnd;
    void ade(int u1,int v1){v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
    void getsiz(int u)
    {
    	siz[u]=1;
    	view(u,k)if(v[k]!=fa[u])
    	{
    		getsiz(v[k]),siz[u]+=siz[v[k]];
    		if(siz[v[k]]>siz[wson[u]])wson[u]=v[k];
    	}
    }
    void gettop(int u,int anc)
    {
    	top[u]=anc,dfn[u]=++tim;
    	if(wson[u])gettop(wson[u],anc);
    	view(u,k)if(v[k]!=fa[u]&&v[k]!=wson[u])gettop(v[k],v[k]);
    }
    int mo(int x){if(x>=mod)return x-mod;if(x<0)return x+mod;return x;}
    int build(int l,int r)
    {
    	int u=++cntnd;
    	if(l==r){return u;}
    	ls=build(l,mi),rs=build(mi+1,r);
    	return u;
    }
    int add(int u,int l,int r,int x,int y,int vers)
    {
    	int nu=vers==ver[u]?u:++cntnd;
    	if(x<=l&&r<=y){son[nu][0]=ls,son[nu][1]=rs,ver[nu]=vers,tr[nu]=mo(tr[u]+r-l+1),mk[nu]=mo(mk[u]+1);return nu;}
    	ver[nu]=vers,tr[nu]=mo(tr[u]+y-x+1),mk[nu]=mk[u];
    	if(x<=mi)son[nu][0]=add(ls,l,mi,x,min(mi,y),vers);
    	else son[nu][0]=ls;
    	if(y>mi)son[nu][1]=add(rs,mi+1,r,max(x,mi+1),y,vers);
    	else son[nu][1]=rs;
    	return nu;
    }
    int ask(int ua,int ub,int l,int r,int x,int y,int ad)
    {
    	if(x<=l&&r<=y){return mo(mo(tr[ua]-tr[ub])+(LL)ad*(LL)(y-x+1)%mod);}
    	int lans=0,rans=0;
    	if(x<=mi)lans=ask(lsa,lsb,l,mi,x,min(mi,y),mo(ad+mo(mk[ua]-mk[ub])));
    	if(y>mi)rans=ask(rsa,rsb,mi+1,r,max(x,mi+1),y,mo(ad+mo(mk[ua]-mk[ub])));
    	return mo(lans+rans);
    }
    int main()
    {
    	memset(fir,-1,sizeof(fir));
    	n=read(),q=read();
    	rep(i,2,n)fa[i]=read()+1,ade(fa[i],i);
    	getsiz(1),gettop(1,1);rt[0]=build(1,n);
    	rep(i,1,n)
    	{
    		rt[i]=rt[i-1];int x=i;
    		while(top[x]!=1){rt[i]=add(rt[i],1,n,dfn[top[x]],dfn[x],i);x=fa[top[x]];}
    		rt[i]=add(rt[i],1,n,1,dfn[x],i);
    	}
    	while(q--)
    	{
    		int l=read()+1,r=read()+1,x=read()+1,ans=0;
    		while(top[x]!=1){ans=mo(ans+ask(rt[r],rt[l-1],1,n,dfn[top[x]],dfn[x],0));x=fa[top[x]];}
    		ans=mo(ans+ask(rt[r],rt[l-1],1,n,1,dfn[x],0));
    		write(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux每日命令(29): chown命令
    linux每日命令(28): charp命令
    linux每日命令(27): chmod命令
    linux每日命令(26):Linux文件属性详解
    linux每日命令(25): linux文件类型与扩展名
    linux每日命令(24): linux目录结构
    linux每日命令(23): find命令之xargs
    linux每日命令(22): find命令参数详解
    2017年12月31日
    Python使用otp实现二步验证
  • 原文地址:https://www.cnblogs.com/xzyf/p/10423891.html
Copyright © 2011-2022 走看看