• 【洛谷5305】[GXOI/GZOI2019] 旧词(LCA套路题)


    点此看题面

    • 给定一棵(n)个点的以(1)为根的树。
    • (q)次询问,每次给定(x,y),求(sum_{i=1}^xdepth(LCA(i,y))^k)
    • (n,qle5 imes10^4)

    经典(LCA)套路

    实在是经典啊。

    核心思想是发现从(x)到根和从(y)到根的路径的交集正好是从(LCA(x,y))到根的路径。

    定义一种深度(d)的权值为(d^k-(d-1)^k),相当于是做了一个差分。

    然后考虑(depth(LCA(x,y))^k),如果我们给(x)到根的路径上所有点都加上(1)的次数,然后询问从(y)到根路径上所有点的次数( imes)对应深度的权值,则修改路径和询问路径的交集就是(LCA(x,y))到根的路径,那么询问到的总值相当于给差分做了一遍前缀和,就是(depth(LCA(x,y))^k)

    多个(x)和单个(y)之间也是一样的,因为这个贡献是可以叠加计算的。

    所以我们离线询问,按照(x)排序。

    枚举(x),利用树剖将它的贡献表示到树上,然后用当前前缀上的询问的对应的(y)查询。

    代码:(O(nlog^2n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 50000
    #define X 998244353
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,m,k,ans[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[N+5];
    struct Q {int p,x,y;I bool operator < (Con Q& o) Con {return x<o.x;}}q[N+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    namespace T//树链剖分
    {
    	int v[N+5],d,dfn[N+5],fac[N+5],D[N+5],f[N+5],g[N+5],sz[N+5],tp[N+5];
    	class SegmentTree
    	{
    		private:
    			#define PT CI l=1,CI r=n,CI rt=1
    			#define LT l,mid,rt<<1
    			#define RT mid+1,r,rt<<1|1
    			#define PU(x) (V[x]=(V[x<<1]+V[x<<1|1])%X)
    			#define PD(x) (F[x]&&(T(x<<1,F[x]),T(x<<1|1,F[x]),F[x]=0))
    			#define T(x,v) (V[x]=(1LL*P[x]*(v)+V[x])%X,F[x]+=v)
    			int V[N<<2],P[N<<2],F[N<<2];
    		public:
    			I void Build(PT)//建树
    			{
    				if(l==r) return (void)(P[rt]=v[D[fac[l]]]);RI mid=l+r>>1;
    				Build(LT),Build(RT),P[rt]=(P[rt<<1]+P[rt<<1|1])%X;//统计子树内权值总和
    			}
    			I void U(CI L,CI R,PT)//区间修改,次数加1
    			{
    				if(L<=l&&r<=R) return (void)T(rt,1);RI mid=l+r>>1;PD(rt);
    				L<=mid&&(U(L,R,LT),0),R>mid&&(U(L,R,RT),0),PU(rt);
    			}
    			I int Q(CI L,CI R,PT)//区间询问次数×权值
    			{
    				if(L<=l&&r<=R) return V[rt];RI mid=l+r>>1;PD(rt);
    				return ((L<=mid?Q(L,R,LT):0)+(R>mid?Q(L,R,RT):0))%X;
    			}
    	}S;
    	I void dfs1(CI x)//树剖第一遍dfs
    	{
    		sz[x]=1;for(RI i=lnk[x];i;i=e[i].nxt) D[e[i].to]=D[x]+1,
    			dfs1(e[i].to),sz[x]+=sz[e[i].to],sz[e[i].to]>sz[g[x]]&&(g[x]=e[i].to);
    	}
    	I void dfs2(CI x,CI t)//树剖第二遍dfs
    	{
    		if(fac[dfn[x]=++d]=x,tp[x]=t,!g[x]) return;dfs2(g[x],t);
    		for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^g[x]&&(dfs2(e[i].to,e[i].to),0);
    	}
    	I void Init()//初始化
    	{
    		RI i;for(i=1;i<=n;++i) v[i]=QP(i,k);for(i=n;i;--i) v[i]=(v[i]-v[i-1]+X)%X;//求出每种深度对应的权值
    		D[1]=1,dfs1(1),dfs2(1,1),S.Build();//树剖,建线段树
    	}
    	I void A(RI x) {W(x) S.U(dfn[tp[x]],dfn[x]),x=f[tp[x]];}//给到根路径次数加1
    	I int Q(RI x,RI t=0) {W(x) t=(t+S.Q(dfn[tp[x]],dfn[x]))%X,x=f[tp[x]];return t;}//询问到根路径次数×权值
    }
    int main()
    {
    	RI i;for(read(n,m,k),i=2;i<=n;++i) read(T::f[i]),add(T::f[i],i);T::Init();
    	RI x,y;for(i=1;i<=m;++i) read(q[i].x,q[i].y),q[i].p=i;sort(q+1,q+m+1);//离线
    	RI j=1;for(i=1;i<=n;++i) {T::A(i);W(j<=m&&q[j].x==i) ans[q[j].p]=T::Q(q[j].y),++j;}//加上当前点贡献,然后处理当前前缀的询问
    	for(i=1;i<=m;++i) writeln(ans[i]);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    在小气的神的Blog上看到的一段Video
    一个在.net下进行用户模拟的类
    PDC每日视频
    今天才知有一个CollectionBase类,惭愧
    “EditandContinue”特性
    Codeforces Round #597 (Div. 2) A. Good ol' Numbers Coloring
    单据号生成
    JAR包
    框架之间传值
    Eclipse3.4发布 新特性展示
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5305.html
Copyright © 2020-2023  润新知