1 条题解
-
0
自动搬运
来自洛谷,原作者为

Owen_codeisking
前OIer/ACMer/柚子厨/酒姬民搬运于
2025-08-24 21:46:52,当前版本为作者最后更新于2018-12-23 19:17:39,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
从下午三点开此题调到到七点, 掉此题的感觉真的是太爽了!!!
而且我觉得这道题对于练整体二分非常的好,就是写的人有点少。
不过为什么盘子是水果的子路径才是接住啊。。。不应该盘子比水果大的嘛。。。
我们将此路径覆盖分两类讨论:
不妨令
1、
那么我们发现其实路径一个端点在 ,另一个不在除 外 的路径上的点 的子树内就行了,即 。其实用树剖一直向上跳,跳到离 最近的点且其子树内包含 就是 了。
2、
那么一个点在 ,另一个点在 就行了
发现可以做一遍扫描线,直接暴力树套树。在内层线段树动态开点,然后二分答案, 验证,时间复杂度 ,空间复杂度
那有没有更好的解法呢?发现没有离线,第 小,
我们可以请出我们的整体二分!
然后正解就是扫描线+整体二分了。把矩形差分一下,然后区间加,单点查,套一个差分的树状数组就好了。时间复杂度 ,空间复杂度
#include <bits/stdc++.h> #define lowbit(x) ((x)&(-(x))) using namespace std; const int maxn=40000+10; int n,m,Q,c[maxn],ans[maxn],mp[maxn],lim,head[maxn],to[maxn<<1],nxt[maxn<<1],tot,cnt; int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn],st[maxn],ed[maxn],tim; struct Query{ int op,x,l,r,k,v,id; }q[maxn*5],q1[maxn*5],q2[maxn*5]; bool cmp(Query a,Query b){ if(a.x!=b.x) return a.x<b.x; return a.op<b.op; } inline void read(int &x){ x=0;int f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} if(f==-1) x=-x; } void print(int x){ if(x<0){putchar('-');x=-x;} if(x>9) print(x/10); putchar(x%10+'0'); } inline void upd(int x,int y){ for(;x<=n;x+=lowbit(x)) c[x]+=y; } inline int sum(int x){ int ans=0; for(;x;x-=lowbit(x)) ans+=c[x]; return ans; } inline void add(int x,int y){ to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } void dfs1(int x,int f){ fa[x]=f;siz[x]=1; dep[x]=dep[f]+1; int maxson=-1; for(int i=head[x],y;i;i=nxt[i]){ y=to[i]; if(y==f) continue; dfs1(y,x); siz[x]+=siz[y]; if(siz[y]>maxson){ maxson=siz[y]; son[x]=y; } } } void dfs2(int x,int topf){ top[x]=topf; st[x]=++tim; if(son[x]) dfs2(son[x],topf); for(int i=head[x],y;i;i=nxt[i]){ y=to[i]; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); } ed[x]=tim; } int LCA(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); return x; } int getson(int x,int y){ while(top[x]!=top[y]){ if(fa[top[x]]==y) return top[x]; x=fa[top[x]]; } return son[y]; } void solve(int L,int R,int l,int r){ if(L>R) return ; if(l==r){ for(int i=L;i<=R;i++) if(q[i].op==2) ans[q[i].id]=mp[l]; return ; } int mid=(l+r)>>1,cnt1=0,cnt2=0,val; for(int i=L;i<=R;i++){ if(q[i].op==1){ if(q[i].k<=mid){ upd(q[i].l,q[i].v);upd(q[i].r+1,-q[i].v); q1[++cnt1]=q[i]; } else q2[++cnt2]=q[i]; } else { val=sum(q[i].l); if(val>=q[i].k) q1[++cnt1]=q[i]; else q[i].k-=val,q2[++cnt2]=q[i]; } } for(int i=1;i<=cnt1;i++) q[L+i-1]=q1[i]; for(int i=1;i<=cnt2;i++) q[L+i+cnt1-1]=q2[i]; solve(L,L+cnt1-1,l,mid);solve(L+cnt1,R,mid+1,r); } int main() { read(n),read(m),read(Q); int x,y,z,l,r,k,lca; for(int i=1;i<n;i++){ read(x),read(y); add(x,y);add(y,x); } dfs1(1,0);dfs2(1,1); for(int i=1;i<=m;i++){ read(x),read(y),read(k);mp[i]=k; if(st[x]>st[y]) swap(x,y); lca=LCA(x,y); if(lca==x){ z=getson(y,x); if(st[z]>1){ q[++cnt]=(Query){1,1,st[y],ed[y],k,1,0}; q[++cnt]=(Query){1,st[z],st[y],ed[y],k,-1,0}; } if(ed[z]<n){ q[++cnt]=(Query){1,st[y],ed[z]+1,n,k,1,0}; q[++cnt]=(Query){1,ed[y]+1,ed[z]+1,n,k,-1,0}; } } else { q[++cnt]=(Query){1,st[x],st[y],ed[y],k,1,0}; q[++cnt]=(Query){1,ed[x]+1,st[y],ed[y],k,-1,0}; } } sort(mp+1,mp+m+1); lim=unique(mp+1,mp+m+1)-mp-1; for(int i=1;i<=cnt;i++) q[i].k=lower_bound(mp+1,mp+lim+1,q[i].k)-mp; for(int i=1;i<=Q;i++){ read(x),read(y),read(k); if(st[x]>st[y]) swap(x,y); q[++cnt]=(Query){2,st[x],st[y],0,k,0,i}; } sort(q+1,q+cnt+1,cmp); solve(1,cnt,1,lim); for(int i=1;i<=Q;i++) printf("%d\n",ans[i]); return 0; }
- 1
信息
- ID
- 2315
- 时间
- 6000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者