zoukankan      html  css  js  c++  java
  • [GXOI/GZOI2019]旧词

    很像LNOI 2014 LCA那道题。

    同样的套路,离线以后直接扫描线。

    k=1的话就是原题。

    考虑一般情况。

    原本的做法是对x到根的这条链做一下区间+1操作,目的是为了是的在深度为i的位置得到的贡献是i。

    因此,我们只需要构造出一个任意一个位置都满足前缀和为i^k的序列即可。

    然后每次把这个序列加到这条链上,由于每个点的深度固定,因此每个位置每次增加的数字也是固定的,可以区间打标记线段树维护。

    考虑怎么构造这个序列,显然直接把1k,2k,3k,4k......差分就可以了。

    #include<bits/stdc++.h>
    #define N 220000
    #define eps 1e-7
    #define inf 1e9+7
    #define db double
    #define ll long long
    #define ldb long double
    using namespace std;
    inline int read()
    {
    	char ch=0;
    	int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*flag;
    }
    const int mo=998244353;
    int ksm(int x,int k)
    {
    	int ans=1;
    	while(k)
    	{
    		if(k&1)ans=1ll*ans*x%mo;
    		k>>=1;x=1ll*x*x%mo;
    	}
    	return ans;
    }
    struct edge{int to,nxt;}e[N*2];
    int num,head[N];
    inline void add(int x,int y){e[++num]={y,head[x]};head[x]=num;}
    struct question{int x,y,id;}p[N];
    bool cmp(question a,question b){return a.x<b.x;}
    int n,q,k,times,v[N],id[N],sz[N],fa[N],dep[N],son[N],top[N],ans[N];
    void dfs1(int x,int t)
    {
    	sz[x]=1;dep[x]=t;
    	for(int i=head[x];i!=-1;i=e[i].nxt)
    	{
    		int to=e[i].to;
    		if(to==fa[x])continue;
    		dfs1(to,t+1);sz[x]+=sz[to];
    		if(sz[son[x]]<sz[to])son[x]=to;
    	}
    }
    void dfs2(int x,int tp)
    {
    	top[x]=tp;v[++times]=x;id[x]=times; 	
    	if(son[x])dfs2(son[x],tp);
    	for(int i=head[x];i!=-1;i=e[i].nxt)
    	{
    		int to=e[i].to;
    		if(top[to])continue;
    		dfs2(to,to);
    	}
    }
    struct Segment_Tree
    {
    	#define lson o<<1
    	#define rson o<<1|1
    	#define mid ((l+r)>>1)
    	int f[N*4],sumv[N*4],addv[N*4];
    	inline void pushup(int o)
    	{
    		sumv[o]=(sumv[lson]+sumv[rson])%mo;
    	}
    	inline void pushdown(int o)
    	{
    		addv[lson]=(addv[lson]+addv[o])%mo;
    		addv[rson]=(addv[rson]+addv[o])%mo;
    		sumv[lson]=(sumv[lson]+(1ll*addv[o]*f[lson]%mo))%mo;
    		sumv[rson]=(sumv[rson]+(1ll*addv[o]*f[rson]%mo))%mo;
    		addv[o]=0;
    	}
    	void build(int o,int l,int r)
    	{
    		if(l==r)
    		{
    			int t=dep[v[l]];
    			f[o]=(ksm(t,k)-ksm(t-1,k))%mo;
    			return;
    		}
    		build(lson,l,mid);build(rson,mid+1,r);
    		f[o]=(f[lson]+f[rson])%mo;
    	}
    	void optadd(int o,int l,int r,int ql,int qr)
    	{
    		if(ql<=l&&r<=qr)
    		{
    			addv[o]=(addv[o]+1)%mo;
    			sumv[o]=(sumv[o]+f[o])%mo;
    			return;
    		}
    		pushdown(o);
    		if(ql<=mid)optadd(lson,l,mid,ql,qr);
    		if(qr>mid)optadd(rson,mid+1,r,ql,qr);
    		pushup(o);
    	}
    	int query(int o,int l,int r,int ql,int qr)
    	{
    		if(ql<=l&&r<=qr)return sumv[o];
    		pushdown(o);
    		int ans=0;
    		if(ql<=mid)ans=(ans+query(lson,l,mid,ql,qr))%mo;
    		if(qr>mid)ans=(ans+query(rson,mid+1,r,ql,qr))%mo;
    		return ans;
    	}
    }T;
    void update(int x)
    {
    	while(x)T.optadd(1,1,n,id[top[x]],id[x]),x=fa[top[x]];
    }
    int query(int x)
    {
    	int ans=0;
    	while(x)ans=(ans+T.query(1,1,n,id[top[x]],id[x]))%mo,x=fa[top[x]];
    	return ans;
    }
    int main()
    {
    	n=read();q=read();k=read();
    	num=-1;memset(head,-1,sizeof(head));
    	for(int i=2;i<=n;i++)fa[i]=read(),add(fa[i],i);
    	dfs1(1,1);dfs2(1,1);T.build(1,1,n); 
    	for(int i=1;i<=q;i++)p[i].x=read(),p[i].y=read(),p[i].id=i;
    	sort(p+1,p+q+1,cmp);
    	for(int i=1,j=0;i<=n;i++)
    	{
    		update(i);
    		while(j!=q&&p[j+1].x==i)j++,ans[p[j].id]=query(p[j].y);
    	}
    	for(int i=1;i<=q;i++)printf("%d
    ",(ans[i]%mo+mo)%mo);
    	return 0;
    }
    
  • 相关阅读:
    jQury+Ajax与C#后台交换数据
    loadrunner 测试问题汇总
    Loadrunner脚本学习总结
    sar命令详解
    用sar进行CPU利用率的分析
    centos7-sar工具的安装过程及其简单应用
    shell if [ -d filename]
    shell脚本自带变量的含义
    Sublime Text2使用规则
    selenium grid结构图
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/10770733.html
Copyright © 2011-2022 走看看