套上线段树分治。

用模拟费用流进行理解。

若一个点加入的时候子树内汇点边没有流满,那么直接流就行了。

如果流的全是子树内的,那么直接看能否替换即可,否则有反向边,往上跳到第一个全是子树内的,替换掉即可。

加入一个点的时候:

  • 找到父亲中第一个全是子树内的流,找不到,则直接流,顺便将祖先全部减去 1
  • 找到,则替换掉子树内最小的一个员工,若不能替换就byebye,否则直接替换,顺便将上面减去 1,将删掉的员工上面加上 1。

我们需要维护子树内的最小值以及其位置,使用 dfn 线段树,叶子维护 multiset,上面维护最值。

我们有哪些操作需要撤销?直接记录所有对线段树的操作,对应回退即可。

#include<bits/stdc++.h> 
using namespace std;
#define N 400005
#define ls u<<1
#define rs u<<1|1
#define ll long long
#define inf 0x7fffffff
#define pii pair<int,int>
int n,k,m;
int w[N],pos[N],adt[N],vis[N],siz[N],son[N],dfn[N],rnk[N],top[N],dad[N],tot;
basic_string<int> G[N],qry[N]; 
void dfs(int u){siz[u]=1;for(int v:G[u])dfs(v),siz[u]+=siz[v],son[u]=siz[son[u]]>siz[v]?son[u]:v;}
void dfs(int u,int t){
	top[u]=t;rnk[dfn[u]=++tot]=u;
	if(son[u])dfs(son[u],t);
	for(int v:G[u])if(v^son[u])dfs(v,v);
}
void insert(int u,int l,int r,int L,int R,int id){
	if(L<=l&&r<=R)return qry[u]+=id,void();
	int m=(l+r)>>1;
	if(m>=L)insert(ls,l,m,L,R,id);
	if(m<R)insert(rs,m+1,r,L,R,id);
}
namespace sgt1{
	pii tr[N<<2]; 
	multiset<pii> p[N<<2];
	void build(int u,int l,int r){
		tr[u]={inf,0};
		if(l==r)return;
		int m=(l+r)>>1;build(ls,l,m),build(rs,m+1,r);
	}
	void upd(int u,int l,int r,int x,int id,int op){
		if(l==r){
			if(op==-1)p[u].erase({w[id],id});
			else p[u].insert({w[id],id});
			tr[u]=!p[u].size()?pii{inf,0}:*p[u].begin();
			return;
		}
		int m=(l+r)>>1;
		if(m>=x)upd(ls,l,m,x,id,op);
		else upd(rs,m+1,r,x,id,op);
		tr[u]=min(tr[ls],tr[rs]);
	}
	pii ask(int u,int l,int r,int L,int R){
		if(L<=l&&r<=R)return tr[u];
		int m=(l+r)>>1;pii ans={inf,0};
		if(m>=L)ans=min(ans,ask(ls,l,m,L,R));
		if(m<R)ans=min(ans,ask(rs,m+1,r,L,R));
		return ans;
	}
}
namespace sgt2{
	int tr[N<<2],tag[N<<2];
	void pull(int u){tr[u]=min(tr[ls],tr[rs]);}
	void pushtag(int u,int x){tag[u]+=x;tr[u]+=x;}
	void push(int u){if(tag[u])pushtag(ls,tag[u]),pushtag(rs,tag[u]),tag[u]=0;}
	void build(int u,int l,int r){
		if(l==r)return tr[u]=siz[rnk[l]],void();
		int m=(l+r)>>1;
		build(ls,l,m),build(rs,m+1,r);
		pull(u);
	}
	void upd(int u,int l,int r,int L,int R,int x){
		if(L<=l&&r<=R)return pushtag(u,x);
		push(u);int m=(l+r)>>1;
		if(m>=L)upd(ls,l,m,L,R,x);
		if(m<R)upd(rs,m+1,r,L,R,x);
		pull(u);
	}
	int ask2(int u,int l,int r){
		if(l==r)return tr[u]?inf:rnk[l];
		push(u);int m=(l+r)>>1;
		return tr[rs]?ask2(ls,l,m):ask2(rs,m+1,r);
	}
	int ask(int u,int l,int r,int L,int R){
		if(L<=l&&r<=R)return tr[u]?inf:ask2(u,l,r);
		push(u);int m=(l+r)>>1,ans;
		if(m<R&&(ans=ask(rs,m+1,r,L,R))!=inf)return ans;
		if(m>=L)return ask(ls,l,m,L,R);
		return inf;
	}	
}
int a[N],opt[N],t;ll ans;
inline void add(int id){
	int u=pos[id];ans+=w[id];
	sgt1::upd(1,1,n,dfn[pos[id]],id,1);
	while(u)sgt2::upd(1,1,n,dfn[top[u]],dfn[u],-1),u=dad[top[u]];	
}
inline void del(int id){
	int u=pos[id];ans-=w[id];
	sgt1::upd(1,1,n,dfn[pos[id]],id,-1);
	while(u)sgt2::upd(1,1,n,dfn[top[u]],dfn[u],1),u=dad[top[u]];	
}
void solve(int u,int l,int r){
	int tt=t;
	//add
	for(int id:qry[u]){
		int u=pos[id];
		while(u&&sgt2::ask(1,1,n,dfn[top[u]],dfn[u])==inf)u=dad[top[u]];
		if(!u)a[++t]=id,opt[t]=1,add(id);
		else{
			int x=sgt2::ask(1,1,n,dfn[top[u]],dfn[u]);
			int tid=sgt1::ask(1,1,n,dfn[x],dfn[x]+siz[x]-1).second;
			if(w[tid]<w[id])a[++t]=id,opt[t]=1,add(id),a[++t]=tid,opt[t]=-1,del(tid);
		} 
	}
	int m=(l+r)>>1;
	if(l==r)printf("%lld ",ans);
	else solve(ls,l,m),solve(rs,m+1,r);
	//del
	while(tt!=t){
		if(opt[t]==1)del(a[t]);
		else add(a[t]);
		--t;
	}
}
int main(){
	//freopen("transfer3.in","r",stdin);
	//freopen("transfer.out","w",stdout);
	scanf("%d%d%d%d",&w[0],&n,&k,&m);
	for(int v=2;v<=n;v++)scanf("%d",&dad[v]),G[dad[v]]+=v;//printf("%d %d\n",dad[v],v);
	for(int i=1;i<=k;i++)scanf("%d%d",&pos[i],&w[i]);
	dfs(1);dfs(1,1);sgt2::build(1,1,n);sgt1::build(1,1,n);
	for(int i=1,op,x;i<=m;i++){
		scanf("%d",&op);
		if(op==1)++k,scanf("%d%d",&pos[k],&w[k]),adt[k]=i;
		else scanf("%d",&x),vis[x]=1,insert(1,0,m,adt[x],i-1,x);//printf("add %d %d %d\n",adt[x],i-1,x);
	}
	for(int i=1;i<=k;i++)if(!vis[i])insert(1,0,m,adt[i],m,i);//printf("add %d %d %d\n",adt[i],m,i);
	solve(1,0,m);
}
/*
212365 312130 212365 171257 171257 129289 73320
*/