这道题拿左偏树做的话时间复杂度好像是 $O(n log n)$ 的,拿 $Splay$ 的话就是 $O(n log^2 n)$ 的.
$Splay$ 真恶心,真心不好写,要不是可以练习代码能力的话我才不用 $Splay$.
code:
#include <bits/stdc++.h> #define ll long long #define N 300006 #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; const ll inf=7e18+2; ll h[N]; struct opt { int a; ll v; }tree[N]; int DE; int n,m,edges,tot,FL,Ans1[N],Ans2[N],ge[N]; int dep[N],hd[N],to[N],nex[N],rt[N],ou[N]; namespace BST { #define lson s[x].ch[0] #define rson s[x].ch[1] struct node { ll v,a,b; int si,ch[2],f,id; void ini() { v=0,a=1,b=0; si=1,ch[0]=ch[1]=f=id=0; } }s[N*20]; int tot; stack<int>S; inline int get(int x) { return s[s[x].f].ch[1]==x; } inline int newnode() { if(S.empty()) return ++tot; else { int u=S.top(); S.pop(); return u; } } inline void pushup(int x) { s[x].si=s[lson].si+s[rson].si+1; } inline void mark_a(int x,ll a) { s[x].a*=a,s[x].b*=a; if(s[x].v!=inf&&s[x].v!=-inf) s[x].v*=a; } inline void mark_b(int x,ll b) { s[x].b+=b; if(s[x].v!=inf&&s[x].v!=-inf) s[x].v+=b; } inline void pushdown(int x) { if(s[x].a!=1) { if(lson) mark_a(lson,s[x].a); if(rson) mark_a(rson,s[x].a); s[x].a=1; } if(s[x].b) { if(lson) mark_b(lson,s[x].b); if(rson) mark_b(rson,s[x].b); s[x].b=0; } } int ins(int &x,int ff,int id,ll v) { if(!x) { x=newnode(); s[x].ini(); s[x].f=ff,s[x].id=id,s[x].v=v; return x; } ++s[x].si; pushdown(x); return ins(s[x].ch[v>s[x].v],x,id,v); } inline int find(int x,ll v) { int r=0; while(1) { if(!x) break; pushdown(x); if(s[x].v>=v) r=x,x=lson; else x=rson; } return r; } inline void rotate(int x) { int old=s[x].f,fold=s[old].f,which=get(x); s[old].ch[which]=s[x].ch[which^1]; if(s[old].ch[which]) s[s[old].ch[which]].f=old; s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; if(fold) s[fold].ch[s[fold].ch[1]==old]=x; pushup(old),pushup(x); } void splay(int x,int &tar) { int u=s[tar].f; for(int fa;(fa=s[x].f)!=u;rotate(x)) if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x); tar=x; } void ope(int &x,int y) { if(s[y].v!=-inf&&s[y].v!=inf) { int p=ins(x,0,s[y].id,s[y].v); if((rand()%3)==0) splay(p,x); } pushdown(y); if(s[y].ch[0]) ope(x,s[y].ch[0]); if(s[y].ch[1]) ope(x,s[y].ch[1]); S.push(y); } void del(int x) { if(!x) return; if(s[x].v!=inf&&s[x].v!=-inf) { Ans1[FL]+=1; ou[s[x].id]=1; Ans2[s[x].id]+=dep[ge[s[x].id]]-dep[FL]; } pushdown(x); if(lson) del(lson); if(rson) del(rson); S.push(x); } #undef lson #undef rson }; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void merge(int x,int y) { if(BST::s[rt[x]].si<BST::s[rt[y]].si) swap(rt[x],rt[y]); BST::ope(rt[x],rt[y]); } void dfs(int x,int ff) { dep[x]=dep[ff]+1; BST::ins(rt[x],0,0,inf); BST::ins(rt[x],0,0,-inf); for(int i=hd[x];i;i=nex[i]) { int y=to[i]; dfs(y,x),merge(x,y); } FL=x; int q=BST::find(rt[x],h[x]); BST::splay(q,rt[x]); BST::s[BST::s[q].ch[0]].f=0; BST::del(BST::s[q].ch[0]); BST::s[q].ch[0]=0; BST::pushup(q); if(x!=1) { if(tree[x].a==0) BST::mark_b(q,tree[x].v); if(tree[x].a==1) BST::mark_a(q,tree[x].v); } } int main() { // setIO("input"); int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;++i) scanf("%lld",&h[i]); for(i=2;i<=n;++i) scanf("%d%d%lld",&j,&tree[i].a,&tree[i].v),add(j,i); for(i=1;i<=m;++i) { ll v; int u; scanf("%lld%d",&v,&u); ge[i]=u; BST::ins(rt[u],0,i,v); } dfs(1,0); for(i=1;i<=n;++i) printf("%d ",Ans1[i]); for(i=1;i<=m;++i) if(!ou[i]) printf("%d ",dep[ge[i]]); else printf("%d ",Ans2[i]); return 0; }