【CSP-S 2019模拟】T1 —看门人(长链剖分+线段树)
签到水题
长剖维护一下,每次在链顶把链底向上一个个合并轻儿子
用一颗线段树维护单点修改和区间询问即可
考试的时候看错题了…
以为只找向下一条路径
还写了个线段树合并对拍了
我是个瓜皮
#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);
}