【CSP-S 2019模拟】T1 —看门人(长链剖分+线段树)

传送门


签到水题

长剖维护一下,每次在链顶把链底向上一个个合并轻儿子
用一颗线段树维护单点修改和区间询问即可

考试的时候看错题了…
以为只找向下一条路径
还写了个线段树合并对拍了2h2h
我是个瓜皮

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<22|5;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define re register
#define cs const
#define ll long long
#define pb push_back
#define poly vector<int>
#define pii pair<int,int>
#define fi first
#define se second
inline void chemx(ll &a,ll b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int mod=998244353;
inline int Add(int &a,int b){return (a+=b)>=mod?a-=mod:0;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
cs int N=1000005;
int n,m,pw[N];
ll ans[N];
vector<pii> e[N];
vector<int> chain[N];
int dep[N],mxdep[N],son[N],L[N],R[N],fa[N],top[N];
ll dis[N];
ll *f[N],tmp[N<<2],*id;
void dfs1(int u){
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i].fi;
		dep[v]=dep[u]+1,dis[v]=dis[u]+e[u][i].se;
		dfs1(v);
		if(mxdep[v]>mxdep[son[u]])son[u]=v;
	}
	mxdep[u]=mxdep[son[u]]+1;
}
void dfs2(int u,int tp){
	top[u]=tp;
	if(son[u])dfs2(son[u],tp);
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i].fi;
		if(v==son[u])continue;
		dfs2(v,v);
	}
	chain[top[u]].pb(u);
}
namespace Seg{
	ll mx[N<<2],a[N];
	int n;
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	inline void pushup(int u){
		mx[u]=max(mx[lc],mx[rc]);
	}
	void build(int u,int l,int r){
		if(l==r){mx[u]=a[l];return;}
		build(lc,l,mid),build(rc,mid+1,r);
		pushup(u);
	}
	inline void init(int len,ll *f){
		n=len-1;
		for(int i=0;i<=n;i++)a[i]=f[i];
		build(1,0,n);
	}
	void insert(int u,int l,int r,int p,ll k){
		if(l==r){chemx(mx[u],k);return;}
		if(p<=mid)insert(lc,l,mid,p,k);
		else insert(rc,mid+1,r,p,k);
		pushup(u);
	}
	inline void update(int p,ll k){
		insert(1,0,n,p,k);
	}
	ll query(int u,int l,int r,int st,int des){
		if(st>r||l>des)return -1;
		if(st<=l&&r<=des)return mx[u];
		ll res=-1;
		if(st<=mid)chemx(res,query(lc,l,mid,st,des));
		if(mid<des)chemx(res,query(rc,mid+1,r,st,des));
		return res;
	}
	inline ll ask(int l,int r){
		
		ll res=query(1,0,n,l,r);
		return res;
	}
	#undef lc 
	#undef rc
	#undef mid
}
inline ll Addchain(int u,int tt,int v){
	ll res=-1;re int del=dep[v]-dep[u];
	for(int i=0;i<mxdep[v];i++){
		int l=dep[tt]-dep[u]+L[tt]-i-1,r=dep[tt]-dep[u]+R[tt]-i-1;
		ll now=-1;
		if(r>=dep[tt]-dep[u])now=Seg::ask(l,r);
		if(now!=-1)chemx(res,f[v][i]+now);
	}
	for(re int i=0;i<mxdep[v];i++){
		if(f[v][i]>f[u][del+i])f[u][del+i]=f[v][i],Seg::update(del+i,f[u][del+i]);
	}
	if(res!=-1)res-=2*dis[tt];
	return res;
}
inline ll ask(int u,int v){
	int del=dep[v]-dep[u];
	ll res=Seg::ask(del+L[v],del+R[v]);
	if(res!=-1)res-=dis[v];
	return res;
}
inline void calc_ans(int u){
	Seg::init(mxdep[u],f[u]);
	for(re int i=0,v,j,t;i<chain[u].size();i++){
		v=chain[u][i];
		for(j=0;j<e[v].size();j++){
			t=e[v][j].fi;
			if(t==son[v])continue;
			chemx(ans[v],Addchain(u,v,t));
		}
		chemx(ans[v],ask(u,v));
	}
}
void dp(int u){
	f[u][0]=dis[u];
	if(son[u]){
		f[son[u]]=f[u]+1,dp(son[u]);
	}
	for(re int i=0,v;i<e[u].size();i++){
		v=e[u][i].fi;
		if(v==son[u])continue;
		f[v]=id,id+=mxdep[v];
		dp(v);
	}
	if(u==top[u])calc_ans(u);
}
signed main(){
	int size=100<<20;
    __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//提交用这个 
	n=read();memset(ans,-1,sizeof(ans));
	for(int i=1;i<=n;i++)L[i]=read(),R[i]=read();
	for(int i=2,w;i<=n;i++)
		fa[i]=read(),w=read(),e[fa[i]].pb(pii(i,w));
	dep[1]=pw[0]=1;
	for(int i=1;i<=n;i++)pw[i]=mul(pw[i-1],23333);
	dfs1(1),dfs2(1,1);
	id=tmp,f[1]=id,id+=mxdep[1];
	dp(1);int res=0;
	for(int i=1;i<=n;i++)Add(res,mul(pw[n-i],(ans[i]%mod+mod)%mod));
	cout<<res;exit(0);
}
posted @ 2019-09-11 21:38  Stargazer_cykoi  阅读(198)  评论(0编辑  收藏  举报