LGP12361 [eJOI 2024] 糖果售卖 学习笔记
LGP12361 [eJOI 2024] 糖果售卖 学习笔记
前言
\(\text{cyx}\) 居然一遍过了这题吗。还是说他直接复制的标程。
题意简述
给定一棵 \(n\) 个结点的树。每个结点有两个值 \(k_u,t_u\)。“一次行动”是指:你从 \(1\) 开始朝一个选定的点 \(p\) 移动,并带着一个初始为 \(0\) 的计数器。你在处于某个点的一开始,计数器会增加 \(k_u\),然后若满足 \(t_u<k_u\),你就“满足”了点 \(u\)。不同行动间互不干扰。
有 \(n\) 次修改,每次对一个 \(k_u\) 单点加 \(d\)。在每次修改之后回答,当前局面下一次行动最多可能满足多少个点。
\(n,q\le 5\times 10^5\),\(0\le t_i\le 10^9\),\(1\le k_i,d\le 10^9\)。
做法解析
一个点的 \(k_u\) 会对满足其子树内的点做出(可能的)贡献。一个点被满足时会对支持其子树内的点成为答案做出贡献。所以你不妨把问题视作:每次单点修(包括初始赋值)都是在对 \(k'_u\) 搞子树加,每个被满足的点都会对 \(t'_u\) 搞子树加,你输出 \(\max t'_u\) 就行了。
显然是势能线段树题。
代码实现
能写能调,状态十分唐诗。
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=5e5+5;
const lolo Inf=1e18;
int N,Q,X,T[MaxN],Y;
vector<int> Tr[MaxN];
int dfn[MaxN],dcnt,nfd[MaxN],siz[MaxN];
void dfs(int u){
dfn[u]=++dcnt,nfd[dcnt]=u,siz[u]=1;
for(int v : Tr[u])dfs(v),siz[u]+=siz[v];
}
struct SegTree2{
int mx[MaxN<<2],tag[MaxN<<2];
int ls(int u){return u<<1;}
int rs(int u){return (u<<1)|1;}
void pushup(int u){mx[u]=max(mx[ls(u)],mx[rs(u)]);}
void maketag(int u,int x){mx[u]+=x,tag[u]+=x;}
void pushdown(int u){if(tag[u])maketag(ls(u),tag[u]),maketag(rs(u),tag[u]),tag[u]=0;}
void update(int u,int cl,int cr,int dl,int dr,int x){
if(dl<=cl&&cr<=dr){maketag(u,x);return;}
pushdown(u);int cmid=(cl+cr)>>1;
if(dl<=cmid)update(ls(u),cl,cmid,dl,dr,x);
if(dr>cmid)update(rs(u),cmid+1,cr,dl,dr,x);
pushup(u);
}
}SgT2;
struct SegTree1{
lolo mx[MaxN<<2],tag[MaxN<<2];
int ls(int u){return u<<1;}
int rs(int u){return (u<<1)|1;}
void pushup(int u){mx[u]=max(mx[ls(u)],mx[rs(u)]);}
void build(int u,int cl,int cr){
if(cl==cr){mx[u]=-T[nfd[cl]];return;}int cmid=(cl+cr)>>1;
build(ls(u),cl,cmid),build(rs(u),cmid+1,cr);pushup(u);
}
void maketag(int u,int x){mx[u]+=x,tag[u]+=x;}
void pushdown(int u){
if(!tag[u])return;
maketag(ls(u),tag[u]),maketag(rs(u),tag[u]),tag[u]=0;
}
void update(int u,int cl,int cr,int dl,int dr,int x){
if(dl<=cl&&cr<=dr){maketag(u,x);return;}
pushdown(u);int cmid=(cl+cr)>>1;
if(dl<=cmid)update(ls(u),cl,cmid,dl,dr,x);
if(dr>cmid)update(rs(u),cmid+1,cr,dl,dr,x);
pushup(u);
}
void maxser(int u,int cl,int cr,int dl,int dr){
if(cl==cr){
if(mx[u]<0)return;
SgT2.update(1,1,N,cl,cl+siz[nfd[cl]]-1,1);
mx[u]=-Inf;return;
}
pushdown(u);int cmid=(cl+cr)>>1;
if(dl<=cmid&&mx[ls(u)]>=0)maxser(ls(u),cl,cmid,dl,dr);
if(dr>cmid&&mx[rs(u)]>=0)maxser(rs(u),cmid+1,cr,dl,dr);
pushup(u);return;
}
}SgT1;
int main(){
readis(N,Q);
for(int i=2;i<=N;i++)readi(X),Tr[X].push_back(i);
for(int i=1;i<=N;i++)readi(T[i]);
dfs(1);SgT1.build(1,1,N);
for(int i=1,cans;i<=Q;i++){
readis(X,Y);SgT1.update(1,1,N,dfn[X],dfn[X]+siz[X]-1,Y);
SgT1.maxser(1,1,N,1,N);cans=SgT2.mx[1],writil(cans);
}
return 0;
}
浙公网安备 33010602011771号