题解:P17144 [NOI 2026] 木棉(暂无数据)
感觉比 D2T1 简单很多。
考虑假设已知一个 Prufer 序列如何确定原树。首先我们知道,这个删除过程结束之后剩下的节点里面的其中一个一定为
于是模拟上述过程,开一个堆来维护叶子集合,即可做到
回到原题,显然
令
分析一下
因为
因为过程和
二分时,每次 check 操作
树套树
代码:
#include"kapok.h"
#include<bits/stdc++.h>
#define N 200009
#define ls (rt<<1)
#define rs (rt<<1|1)
#define pb push_back
using namespace std;
struct node{
vector<int> a,c;int sz;
void init(vector<int> &aa){
a=aa;sort(a.begin(),a.end());
a.resize(sz=unique(a.begin(),a.end())-a.begin());
c.assign(sz+1,0);
}
void upd(int x,int v){
x=lower_bound(a.begin(),a.end(),x)-a.begin()+1;
for(;x<=sz;x+=(x&-x))c[x]+=v;
}
int qry(int x){
x=lower_bound(a.begin(),a.end(),x)-a.begin();
int v=0;for(;x;x-=(x&-x))v+=c[x];return v;
}
} TT;
vector<int> a;int n;
vector<array<int,4>> Q[N];
int lst[N];
struct SGT{
node tr[N<<2];
void build(int rt,int l,int r){
vector<int> b(r-l+1);
for(int i=l;i<=r;i++)b[i-l]=a[i];
tr[rt].init(b);
if(l^r){
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
}
void upd(int rt,int l,int r,int x,int v){
tr[rt].upd(a[x],v);
if(l^r){
int mid=l+r>>1;
if(x<=mid)upd(ls,l,mid,x,v);
else upd(rs,mid+1,r,x,v);
}
}
int q1(int rt,int l,int r,int ql,int qr,int x){
if(ql>r||qr<l)return 0;
else if(ql<=l&&qr>=r)return tr[rt].qry(x);
else{
int mid=l+r>>1;
return q1(ls,l,mid,ql,qr,x)+q1(rs,mid+1,r,ql,qr,x);
}
}
int q2(int rt,int l,int r,int ql,int qr,int x,int &y){
if(ql>r||qr<l)return n;
else if(ql<=l&&qr>=r){
int s=tr[rt].qry(x),t=r-l+1;
if(y+s-t>0){y+=s-t;return n;}
}
if(l==r)return l;
int mid=l+r>>1,L=q2(ls,l,mid,ql,qr,x,y);
return (L<=r)?L:q2(rs,mid+1,r,ql,qr,x,y);
}
} T;
vector<bool> kapok(int C,int n,int q,vector<int> a,vector<int> l,vector<int> r,vector<int> x,vector<int> y){
::n=n;::a=a;T.build(1,0,n-1);TT.init(a);
vector<bool> ans(q,0);memset(lst,-1,sizeof(lst));
for(int i=0;i<q;i++){
if(x[i]==y[i])continue;
if(l[i]==r[i]){ans[i]=1;continue;}
int t=r[i]-l[i]+1;
if(x[i]!=t)Q[r[i]-1].pb({l[i],x[i],y[i],i});
if(y[i]!=t)Q[r[i]-1].pb({l[i],y[i],x[i],i});
}
for(int r=0;r<n;r++){
if(~lst[a[r]])T.upd(1,0,n-1,lst[a[r]],-1);
else TT.upd(a[r],1);
lst[a[r]]=r;T.upd(1,0,n-1,r,1);
for(auto [l,x,y,id]:Q[r]){
if(y!=r-l+2&&lst[x]>lst[y])continue;
int cnt=x-TT.qry(x)+T.q1(1,0,n-1,0,max(l-1,lst[x]),x)-max(0,lst[x]-l+1);
int t=(cnt<=0||lst[x]>=r)?max(lst[x]+1,l):T.q2(1,0,n-1,max(lst[x]+1,l),r,x,cnt)+1;
ans[id]=(y==((t>r)?r-l+2:min(r-l+2,a[t])));
}
}
return ans;
}