题解:P11295 [NOISG2022 Qualification] Dragonfly
来一个离线做法。
由于我们要求的是一条从
设
接下来考虑怎样才能求出
时间复杂度为
#include<bits/stdc++.h>
using namespace std;
int plen,ptop,pstk[40];
char rdc[1<<20],out[1<<20],*rS,*rT;
#define gc() (rS==rT?rT=(rS=rdc)+fread(rdc,1,1<<20,stdin),(rS==rT?EOF:*rS++):*rS++)
#define pc(x) out[plen++]=(x)
#define flush() fwrite(out,1,plen,stdout),plen=0
template<class T=int>inline T read(){
T x=0;char ch;bool f=1;
while(!isdigit(ch=gc()))if(ch=='-')f^=1;
do x=(x<<1)+(x<<3)+(ch^48);while(isdigit(ch=gc()));
return f?x:-x;
}
inline int read(char*const s){
char *t=s,ch;
while(!isgraph(ch=gc()));
do(*(t++))=ch;while(isgraph(ch=gc()));
return (*t)='\000',t-s;
}
template<class T=int>inline void write(T x){
if(plen>=1000000)flush();
if(!x)return pc('0'),void();
if(x<0)pc('-'),x=-x;
for(;x;x/=10)pstk[++ptop]=x%10;
while(ptop)pc(pstk[ptop--]+'0');
}
inline void write(const char*s){
if(plen>=1000000)flush();
for(int i=0;(*(s+i))!='\000';pc(*(s+(i++))));
}
inline void write(char*const s){
if(plen>=1000000)flush();
for(int i=0;(*(s+i))!='\000';pc(*(s+(i++))));
}
const int Maxn=2e5+5,N=2e6+5;
int n,m;
int b[Maxn],s[Maxn],val[Maxn];
int h[N];
int head[Maxn],to[Maxn<<1],nxt[Maxn<<1],cnt1;
inline void add_e(int u,int v){
to[++cnt1]=v;nxt[cnt1]=head[u];
head[u]=cnt1;
}
int dfn[Maxn],cnt2,si[Maxn];
void dfs(int u,int v){
dfn[u]=++cnt2;si[u]=1;
for(int i=head[u];i;i=nxt[i]){
int y=to[i];if(y==v)continue;
dfs(y,u);si[u]+=si[y];
}
}
int t[Maxn];
inline void add(int x,int d){
for(;x<=n;x+=x&-x)t[x]+=d;
}
inline int query(int l,int r){
int res=0;
for(int x=r;x;x-=x&-x)res+=t[x];
for(int x=l-1;x>0;x-=x&-x)res-=t[x];
return res;
}
int d[Maxn],d1[Maxn];
void solve(int l,int r,int L,int R){
// printf("%d %d:\n",l,r);
// for(int i=L;i<=R;i++)printf("%d ",d[i]);
// puts("");
if(l==r){
for(int i=L;i<=R;i++)val[d[i]]=l;
return;
}int mid=l+r>>1;
for(int i=l;i<=mid;i++)add(dfn[h[i]],1);
int tot1=L-1,tot2=R+1;
for(int j=L;j<=R;j++){
int i=d[j];
if(query(dfn[i],dfn[i]+si[i]-1)>=b[i])d1[++tot1]=i;//,printf("[%d,%d]:%d\n",l,r,i);
else d1[--tot2]=i;
}
for(int j=L;j<=R;j++)d[j]=d1[j];
solve(mid+1,r,tot2,R);
for(int i=l;i<=mid;i++)add(dfn[h[i]],-1);
solve(l,mid,L,tot1);
}
vector<int>Q[Maxn];
int ans[N];
multiset<int>a[Maxn];
int t1[N];
inline void add1(int x,int d){
x=-x;
for(;x;x-=x&-x)t1[x]+=d;
}
inline int query1(int x){
int res=0;
for(;x<=m;x+=x&-x)res+=t1[x];
return res;
}
void Dfs(int u,int v){
if(!a[s[u]].empty())add1(*a[s[u]].begin(),-1);
a[s[u]].insert(-val[u]);
add1(*a[s[u]].begin(),1);
for(int i:Q[u])ans[i]=query1(i);
for(int i=head[u];i;i=nxt[i]){
int y=to[i];if(y==v)continue;
Dfs(y,u);
}add1(*a[s[u]].begin(),-1);
a[s[u]].erase(a[s[u]].find(-val[u]));
if(!a[s[u]].empty())add1(*a[s[u]].begin(),1);
}
int main(){
// freopen("P11295_4.in","r",stdin);
// freopen("P11295.out","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++)b[i]=read(),val[i]=m,d[i]=i;
for(int i=1;i<=n;i++)s[i]=read();
for(int i=1;i<=m;i++)h[i]=read(),Q[h[i]].emplace_back(i);
for(int i=1;i<n;i++){
int u=read(),v=read();
add_e(u,v);add_e(v,u);
}
dfs(1,0);
solve(1,m,1,n);
for(int i=1;i<=n;i++)if(!b[i])val[i]=0;
// for(int i=1;i<=n;i++)printf("val[%d]=%d\n",i,val[i]);
Dfs(1,0);
for(int i=1;i<=m;i++)write(ans[i]),pc(' ');
flush();
return 0;
}
/*
10 10
3 3 3 5 6 9 3 1 7 3
10 10 5 3 7 6 1 10 6 6
2 6 2 7 3 6 6 5 3 4
1 4
6 7
7 9
8 7
3 6
8 10
3 1
6 2
5 2
*/