社区讨论
萌新刚学OI不知道多长时间,树套树求卡常
SP10628COT - Count on a tree参与者 4已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @lo259x7r
- 此快照首次捕获于
- 2023/10/23 08:13 2 年前
- 此快照最后确认于
- 2023/11/03 08:31 2 年前
树剖+树套树,时间复杂度 ,一直挂在 Master Judge,吸氧+指令集也没过掉,随机根节点防卡树剖也没过掉。
这个思路可以用可持久化线段树优化掉一个log,但我只是想知道还能不能继续卡。
CPP#include<bits/stdc++.h>
const int lim=1000000000;
struct Segment{int w,ls,rs;}s[20000005];
int n,m,cnt,seg,a[100005],d[100005],h[100005],f[100005],w[100005],ro[100005],dfn[100005],top[100005],
wson[100005],to[200005],nxt[200005];
inline void addstar(int x,int y){
to[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
}
void fisdfs(int x,int las){
w[x]=1,f[x]=las,d[x]=d[las]+1;
for(int i=h[x];i;i=nxt[i]) if(to[i]!=las){
fisdfs(to[i],x),w[x]+=w[to[i]];
if(w[to[i]]>w[wson[x]]) wson[x]=to[i];
}
}
void secdfs(int x,int las){
static int pos;
dfn[x]=++pos,top[x]=las;
if(!wson[x]) return;
secdfs(wson[x],las);
for(int i=h[x];i;i=nxt[i]) if(to[i]!=f[x]&&to[i]!=wson[x]) secdfs(to[i],to[i]);
}
void update(int &u,int l,int r,int p,int k){
if(u==0) u=++seg;
if(l==r) return s[u].w+=k,void();
int mid=(l+r)>>1;
if(p<=mid) update(s[u].ls,l,mid,p,k);
else update(s[u].rs,mid+1,r,p,k);
s[u].w=s[s[u].ls].w+s[s[u].rs].w;
}
void add(int x,int y){
for(int i=x;i<=n;i+=i&-i) update(ro[i],1,lim,y,1);
}
int posl,posr,mil[505],mir[505];
void preload(int l,int r){
for(int i=l-1;i;i-=i&-i) mil[++posl]=ro[i];
for(int i=r;i;i-=i&-i) mir[++posr]=ro[i];
}
int query(int l,int r,int k){//树套树第k大
if(l==r) return l;
int sum=0,mid=(l+r)>>1;
for(int i=1;i<=posl;i++) sum-=s[s[mil[i]].ls].w;
for(int i=1;i<=posr;i++) sum+=s[s[mir[i]].ls].w;
if(k<=sum){
for(int i=1;i<=posl;i++) mil[i]=s[mil[i]].ls;
for(int i=1;i<=posr;i++) mir[i]=s[mir[i]].ls;
return query(l,mid,k);
}
else{
for(int i=1;i<=posl;i++) mil[i]=s[mil[i]].rs;
for(int i=1;i<=posr;i++) mir[i]=s[mir[i]].rs;
return query(mid+1,r,k-sum);
}
}
int querypath(int x,int y,int k){
using std::swap;
posl=0,posr=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
preload(dfn[top[x]],dfn[x]);
x=f[top[x]];
}
if(d[x]<d[y]) swap(x,y);
preload(dfn[y],dfn[x]);
return query(1,lim,k);
}
int main(){//树剖+树套树 O(nlog^3n)
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n-1;i++){
int x=read(),y=read();
addstar(x,y);
addstar(y,x);
}
fisdfs(1,0),secdfs(1,1);
for(int i=1;i<=n;i++) add(dfn[i],a[i]);
for(int i=1;i<=m;i++){
int x=read(),y=read(),k=read();
write(querypath(x,y,k));
}
return sunflush();
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...