数据结构 杂题选做
数据结构科技树 \(=\emptyset\) 补一补
主席树
板子。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define gc getchar
#define pc putchar
#define mid (l+r>>1)
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N],b[N],rt[N],l,r,k;
struct SGT{
int s[N<<5],ls[N<<5],rs[N<<5],cnt;
inl void build(int &k,int l,int r){
k=++cnt;
if(l==r)return;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
inl void update(int &now,int pst,int l,int r,int x){
now=++cnt,s[now]=s[pst]+1,ls[now]=ls[pst],rs[now]=rs[pst];
if(l==r)return;
if(x<=mid)update(ls[now],ls[pst],l,mid,x);
else update(rs[now],rs[pst],mid+1,r,x);
}
inl int query(int now,int pst,int l,int r,int k){
if(l==r)return l;
if(s[ls[now]]-s[ls[pst]]>=k)return query(ls[now],ls[pst],l,mid,k);
else return query(rs[now],rs[pst],mid+1,r,k-(s[ls[now]]-s[ls[pst]]));
}
}tree;
signed main(){
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=b[i]=read();
sort(b+1,b+n+1);
int t=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+t+1,a[i])-b;
tree.build(rt[0],1,t);
for(int i=1;i<=n;i++)tree.update(rt[i],rt[i-1],1,t,a[i]);
while(m--){
l=read(),r=read(),k=read();
writel(b[tree.query(rt[r],rt[l-1],1,t,k)]);
}
return 0;
}
考虑 \(b\) 所在位置:
1.在 \(a\) 到根的路径上 \(c\) 只可能是 \(a\) 子树内的点 答案 \(min(dep[a],k)*(siz[a]-1)\)
2.在 \(a\) 子树内 \([dep[a]+1,dep[a]+k]\) 的点 每个点贡献为 \(siz[b]-1\)
可以用主席树维护:下标维护深度 子树内查询即可
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define gc getchar
#define pc putchar
#define mid (l+r>>1)
const int N=3e5+5;
const int M=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,q,u,v,dep[N],siz[N],rt[N],dfn[N],dfs_clock,rev[N],ans,p,k;
int head[N],nxt[N<<1],to[N<<1],cnt;
struct seg_tree{
int s[N<<5],ls[N<<5],rs[N<<5],cnt;
inl void build(int &k,int l,int r){
k=++cnt;
if(l==r)return;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
inl void update(int &k,int pst,int l,int r,int x,int v){
k=++cnt,s[k]=s[pst]+v,ls[k]=ls[pst],rs[k]=rs[pst];
if(l==r)return;
if(x<=mid)update(ls[k],ls[pst],l,mid,x,v);
else update(rs[k],rs[pst],mid+1,r,x,v);
}
inl int query(int k,int pst,int l,int r,int x,int y){
if(x<=l&&r<=y)return s[k]-s[pst];
int ans=0;
if(x<=mid)ans+=query(ls[k],ls[pst],l,mid,x,y);
if(y>mid)ans+=query(rs[k],rs[pst],mid+1,r,x,y);
return ans;
}
}SGT;
inl void add(int u,int v){
nxt[++cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
inl void dfs1(int x,int fa){
dfn[x]=++dfs_clock;
rev[dfs_clock]=x;siz[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa)continue;
dep[y]=dep[x]+1;
dfs1(y,x);
siz[x]+=siz[y];
}
}
inl void dfs2(int x,int fa){
SGT.update(rt[x],rt[rev[dfn[x]-1]],1,n,dep[x],siz[x]-1);
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa)continue;
dfs2(y,x);
}
}
signed main(){
n=read();q=read();
for(int i=1;i<=n-1;i++){
u=read();v=read();
add(u,v);add(v,u);
}dep[0]=-1;dfs1(1,0);
SGT.build(rt[0],1,n);
dfs2(1,0);
while(q--){
p=read();k=read();
ans=min(dep[p],k)*(siz[p]-1);
ans+=SGT.query(rt[rev[dfn[p]+siz[p]-1]],rt[p],1,n,dep[p]+1,min(n,dep[p]+k));
writel(ans);
}
return 0;
}

浙公网安备 33010602011771号