1. 程式人生 > >雅禮2017 WC模擬(1.21) :看門人(長鏈剖分)

雅禮2017 WC模擬(1.21) :看門人(長鏈剖分)

題意:
給一棵樹,邊長度為1且帶有權值,每個點有[li,ri] ,求其子樹中經過他的長度在[li,ri]的路徑的權值的最小值。
(n1e6)
題解:

要求O(nlogn),可以使用長鏈剖分解決。

因為每條長鏈獨立,所以總的合併深度只有O(n), 加上區間最值,時間複雜度為O(nlogn)

#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); }