CF2079C Dreaming Is Not Harmful 题解
Dreaming is not harmful.
有一个很重要的点:如果不考虑降低员工能力值,那么所有员工被开除的顺序是固定的。先处理出这个序列(可以使用优先队列维护这个过程),记
接着观察到将一个员工的能力值降为
维护一棵带权树
注意特别处理“子树不能包含
时间复杂度
代码中为了方便实现,直接将员工编号替换为其能力值。放代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int I=1e9;
class segtree{
private:
vector<pii> B;
vector<ll> S,T;
inline void pushup(int u){
S[u]=max(S[u<<1],S[u<<1|1]);
}
inline void pushdown(int u){
if(T[u]){
S[u<<1]+=T[u],S[u<<1|1]+=T[u];
T[u<<1]+=T[u],T[u<<1|1]+=T[u],T[u]=0;
}
}
public:
segtree(int n):B(n<<2),S(n<<2),T(n<<2){
function<void(int,int,int)> build=[&](int u,int l,int r){
if(B[u]=make_pair(l,r);l==r)return;
int m=l+r>>1;
build(u<<1,l,m),build(u<<1|1,m+1,r);
};
build(1,0,n-1);
}
void update(int u,int l,int r,int d){
if(B[u].first>r||B[u].second<l)return;
if(l<=B[u].first&&B[u].second<=r){
S[u]+=d,T[u]+=d; return;
}
pushdown(u);
update(u<<1,l,r,d),update(u<<1|1,l,r,d);
pushup(u);
}
inline int all_prod(){return S[1];}
}; // 线段树
class hld{
private:
int n;
vector<int> f,e,h,t,l;
segtree T;
public:
hld(int rt,vector<vector<int> > g):n(g.size()),T(n){
f.resize(n),e.resize(n,1);
h.resize(n,-1),t.resize(n),l.resize(n);
function<void(int)> dfs=[&](int u){
int mx=0;
for(int i:g[u]){
f[i]=u,dfs(i),e[u]+=e[i];
if(e[i]>mx)mx=e[i],h[u]=i;
}
};
int o=0;
function<void(int,bool)> decomp=[&](int u,bool b){
t[u]=b?t[f[u]]:u,l[u]=o++;
if(~h[u])decomp(h[u],true);
for(int i:g[u])
if(i!=h[u])decomp(i,false);
};
f[rt]=-1,dfs(rt),decomp(rt,false);
}
inline void update(int u,int d){
while(~u)T.update(1,l[t[u]],l[u],d),u=f[t[u]];
} // 链加
inline int query(){return T.all_prod();} // 全局 max
}; // 树链剖分
int main(){
ios::sync_with_stdio(false);
int n,m; cin>>n>>m;
vector<pii> e;
for(int i=1;i<n;i++){
int f; cin>>f;
e.emplace_back(f-1,i);
}
vector<int> s(n),o,r(n);
for(auto &i:s)cin>>i,i--;
vector<vector<int> > g(n);
for(auto [u,v]:e)
g[s[u]].emplace_back(s[v]);
priority_queue<int> q;
q.emplace(s[0]);
while(!q.empty()){
int u=q.top(); q.pop();
o.emplace_back(u);
for(int i:g[u])q.emplace(i);
} // 求解原顺序
hld h(s[0],g);
for(int i=0;i<n;i++){
int u=o[i];
h.update(u,-I);
r[u]=i-max(0,h.query());
h.update(u,I+1);
} // 依次求解
while(m--){
int x; cin>>x;
cout<<r[s[x-1]]<<' ';
}
cout<<endl;
return 0;
}