zoukankan      html  css  js  c++  java
  • LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)

    题面

    传送门

    题解

    先考虑(k=1)的情况,我们可以离线处理,从小到大对于每一个(i),令(1)(i)的路径上每个节点权值增加(1),然后对于所有(x=i)的询问查一下(y)到根节点的路径和就是了

    那么(k eq 1)的情况该怎么办呢?我们来考虑一下令(1)(i)的路径上每个节点权值加(1)的本质,相当于是令每个节点(u)增加({dep_u}^k-{dep_{fa_u}}^k),那么用树剖+线段树维护就行了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define inline __inline__ __attribute__((always_inline))
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=E[i].v;i;i=E[i].nx,v=E[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int K=-1,Z=0;
    inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
    void print(R int x){
        if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++K]=z[Z],--Z);sr[++K]='
    ';
    }
    const int N=1e5+5,P=998244353;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    	return res;
    }
    struct eg{int v,nx;}E[N];int head[N],tot;
    inline void Add(R int u,R int v){E[++tot]={v,head[u]},head[u]=tot;}
    struct node;typedef node* ptr;
    struct node{
    	ptr lc,rc;int sum,s,t;
    	inline node();
    	inline void ppd(R int x){sum=add(sum,mul(s,x)),t+=x;}
    	inline void pd(){if(t)lc->ppd(t),rc->ppd(t),t=0;}
    	inline void upd(){sum=add(lc->sum,rc->sum);}
    }e[N<<2],*rt;int cnt;
    inline node::node(){lc=rc=e;}
    int dfn[N],rk[N],bin[N],h[N],dep[N],top[N],fa[N],sz[N],son[N],tim,res,n,q,k;
    void dfs1(int u){
    	sz[u]=1,dep[u]=dep[fa[u]]+1;
    	go(u){
    		dfs1(v),sz[u]+=sz[v];
    		if(sz[v]>sz[son[u]])son[u]=v;
    	}
    }
    void dfs2(int u,int t){
    	top[u]=t,dfn[u]=++tim,rk[tim]=bin[dep[u]];
    	if(!son[u])return;dfs2(son[u],t);
    	go(u)if(v!=son[u])dfs2(v,v);
    }
    void build(ptr &p,int l,int r){
    	p=e+(++cnt);if(l==r)return p->s=rk[l],void();
    	int mid=(l+r)>>1;
    	build(p->lc,l,mid),build(p->rc,mid+1,r);
    	p->s=add(p->lc->s,p->rc->s);
    }
    void update(ptr p,int l,int r,int ql,int qr){
    	if(ql<=l&&qr>=r)return p->ppd(1),void();
    	int mid=(l+r)>>1;p->pd();
    	if(ql<=mid)update(p->lc,l,mid,ql,qr);
    	if(qr>mid)update(p->rc,mid+1,r,ql,qr);
    	p->upd();
    }
    void query(ptr p,int l,int r,int ql,int qr,int d){
    	if(ql<=l&&qr>=r)return res=add(res,add(p->sum,mul(d,p->s))),void();
    	int mid=(l+r)>>1;d+=p->t;
    	if(ql<=mid)query(p->lc,l,mid,ql,qr,d);
    	if(qr>mid)query(p->rc,mid+1,r,ql,qr,d);
    }
    void change(int u){while(top[u])update(rt,1,n,dfn[top[u]],dfn[u]),u=fa[top[u]];}
    int query(int u){res=0;while(top[u])query(rt,1,n,dfn[top[u]],dfn[u],0),u=fa[top[u]];return res;}
    struct qwq{
    	int p,u,id;
    	inline bool operator <(const qwq &b)const{return p<b.p;}
    }st[N];int ans[N];
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),q=read(),k=read();
    	for(R int i=2;i<=n;++i)fa[i]=read(),Add(fa[i],i);
    	fp(i,1,n)bin[i]=ksm(i,k);
    	fd(i,n,1)bin[i]=dec(bin[i],bin[i-1]);
    	dfs1(1),dfs2(1,1),build(rt,1,n);
    	fp(i,1,q)st[i].p=read(),st[i].u=read(),st[i].id=i;
    	sort(st+1,st+1+q);
    	for(R int i=1,j=1;i<=n;++i){
    		change(i);
    		while(j<=q&&st[j].p<=i)ans[st[j].id]=query(st[j].u),++j;
    	}
    	fp(i,1,q)print(ans[i]);
    	return Ot(),0;
    }
    
  • 相关阅读:
    《Glibc内存管理》笔记DAY1
    highcharts相关属性
    SQL Server常用技巧
    常用系统表相关的操作
    SQL递归
    jQuery 根据JSON数据动态生成表格
    string.Format 格式化输出日期
    Easyui修改样式
    submit异步提交 回调的方法
    mvc多个按钮的提交方法
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10745380.html
Copyright © 2011-2022 走看看