雅禮2017 WC模擬(1.21) :看門人(長鏈剖分)
阿新 • • 發佈:2019-01-27
題意:
給一棵樹,邊長度為1且帶有權值,每個點有 ,求其子樹中經過他的長度在的路徑的權值的最小值。
題解:
要求,可以使用長鏈剖分解決。
因為每條長鏈獨立,所以總的合併深度只有, 加上區間最值,時間複雜度為。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
typedef long long LL;
const int N=1e6+50,RLEN=1<<18|1,base=23333,mod=998244353;
const LL INF=0x3f3f3f3f3f3f3f;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?-1:*ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while (!isdigit(ch)) {if(ch==-1) return 0; if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
int n,mxd[N],L[N],R[N],son[N];
LL dis[N],ans[N];
vector <pii> edge[N];
struct node {
node *lc,*rc;
int sze,pri;
LL mxv,v;
inline void upt() {
sze=lc->sze+rc->sze+1;
mxv=max(v,max(lc->mxv,rc->mxv));
}
}Pool[N],*pool=Pool,*rt[N],*null=Pool;
inline node* newnode(LL v) {
++pool;
pool->lc=pool->rc=null;
pool->mxv=pool->v=v;
pool->sze=1;
pool->pri=rand();
return pool;
}
inline void dfs(int x,int f) {
for(auto e:edge[x]) {
int v=e.first, w=e.second;
if(v==f) continue;
dis[v]=dis[x]+w; dfs(v,f);
if(mxd[v]+1>mxd[x]) mxd[x]=mxd[v]+1, son[x]=v;
}
}
inline void lturn(node* &x) {
node *ls=x->lc, *rs=ls->rc;
x->lc=rs; x->upt();
ls->rc=x; ls->upt();
x=ls;
}
inline void inc(node* &x,node *t) {
if(x==null) {x=t; return;}
inc(x->lc,t); x->upt();
if(x->lc->pri>x->pri) lturn(x);
}
inline LL ask(node *x,int l,int r,int L,int R) {
if(x==null) return -INF;
if(L<=l&&r<=R) {return x->mxv;}
int mid=l+x->lc->sze; LL rs=-INF;
if(R<=mid) {
rs=max(rs,ask(x->lc,l,mid-1,L,R));
if(R==mid) rs=max(rs,x->v);
} else if(L>=mid) {
rs=max(rs,ask(x->rc,mid+1,r,L,R));
if(L==mid) rs=max(rs,x->v);
} else {
rs=max(rs,ask(x->lc,l,mid-1,L,R));
rs=max(rs,ask(x->rc,mid+1,r,L,R));
rs=max(rs,x->v);
}
return rs;
}
inline void modify(node *x,int l,int r,int pos,LL v) {
int mid=l+x->lc->sze;
if(mid==pos) x->v=max(x->v,v);
else if(mid>pos) {
modify(x->lc,l,mid-1,pos,v);
} else modify(x->rc,mid+1,r,pos,v);
x->upt();
}
node* stk[N]; int tl;
inline void travel(node *x) {
if(x==null) return;
travel(x->lc);
stk[++tl]=x;
travel(x->rc);
}
inline void dfs2(int x,int f) {
ans[x]=-INF;
if(son[x]) {
dfs2(son[x],x);
rt[x]=rt[son[x]];
if(L[x]<=rt[x]->sze)
ans[x]=max(ans[x],ask(rt[x],1,rt[x]->sze,L[x],min(R[x],rt[x]->sze))-dis[x]);
}
inc(rt[x],newnode(dis[x]));
for(auto e:edge[x]) {
int v=e.first; if(v==f || v==son[x]) continue;
dfs2(v,x);
tl=0; travel(rt[v]);
for(int i=1;i<=tl;i++) {
int l=L[x]-i, r=R[x]-i;
if(r>=0 && l<rt[x]->sze)
ans[x]=max(ans[x], ask(rt[x],0,rt[x]->sze-1,max(l,0),min(r,rt[x]->sze-1))+stk[i]->v-2*dis[x]);
}
for(int i=1;i<=tl;i++)
modify(rt[x],0,rt[x]->sze-1,i,stk[i]->v);
}
}
int main() {
n=rd(); null->mxv=-INF;
for(int i=1;i<=n;i++) L[i]=rd(), R[i]=rd(), rt[i]=null;
for(int i=2;i<=n;i++) {
int f=rd(), w=rd();
edge[f].push_back(pii(i,w));
}
dfs(1,0); dfs2(1,0);
int pw=1,rs=0;
for(int i=n;i>=1;i--) {
int v;
if(ans[i]>-INF) v=(ans[i]%mod+mod)%mod;
else v=mod-1;
rs=(rs+(LL)pw*v)%mod;
pw=(LL)pw*base%mod;
}
printf("%d\n",rs);
}