[XSY3112] 接水果(树上包含路径,整体二分,扫描线)

传送门

给出一棵 n n n个点的树。接下来给出 P P P条树上路径 a i → b i a_i\to b_i aibi,及其权值 c i c_i ci。最后有 Q Q Q个询问,每个询问给出一条树上路径 u i → v i u_i\to v_i uivi,问在包含 u i → v i u_i\to v_i uivi的所有树上路径中(包含指 u i → v i u_i\to v_i uivi a i → b i a_i\to b_i aibi的子路径),权值第 k k k小的路径权值是多少?

不妨设 d e p [ u ] < d e p [ v ] dep[u]<dep[v] dep[u]<dep[v]
l c a ( u , v ) = u lca(u,v)=u lca(u,v)=u,记 p p p u u u在向 v v v方向的儿子,
那么包含 u → v u\to v uv的路径 a → b a\to b ab一定满足: a ∉ s u b t r e e p , b ∈ s u b t r e e v a\not\in subtree_p,b\in subtree_v asubtreep,bsubtreev
l c a ( u , v ) ≠ u lca(u,v)\not=u lca(u,v)=u
那么包含 u → v u\to v uv的路径 a → b a\to b ab一定满足: a ∈ s u b t r e e u , b ∈ s u b t r e e v a\in subtree_u,b\in subtree_v asubtreeu,bsubtreev

也就是说,对于包含 u → v u\to v uv的路径 a → b a\to b ab d f n [ a ] , d f n [ b ] dfn[a],dfn[b] dfn[a],dfn[b]的取值范围是 一段或两端区间。
因此所有符合条件的路径 a → b a\to b ab可以用二维平面上的 一个或两个矩形 表示出来。

原题要求的就是所有包含询问点矩形中权值第 k k k小的。

考虑整体二分,统计一个点在多少个 权值在 [ l , r ] [l,r] [l,r]内的矩形 中出现过。用扫描线解决。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=80010;
struct Edge{int v,nxt;}edge[N];
int n,m,q,cnt,head[N];
int fa[N][20],dep[N],ind,dfn[N],lst[N];
int tot,ans[N],sum[N];
struct Rectangle{int xd,xu,yd,yu,v;}rect[N];
bool operator < (Rectangle a,Rectangle b){return a.v<b.v;} 
struct Point{int x,y,k,id;}pt[N],tmp1[N],tmp2[N];
struct Line{int x,yd,yu,v,id;}line[N];
bool operator < (Line a,Line b){return a.x==b.x?a.id<b.id:a.x<b.x;} 
struct Bit{
    int val[N];
    void modify(int l,int r,int v){
        for(int i=l;i<=n;i+=(i&(-i))) val[i]+=v;
        for(int i=r+1;i<=n;i+=(i&(-i))) val[i]-=v;
    }
    int query(int x){
        int res=0;
        for(;x;x-=(x&(-x))) res+=val[x];
        return res;
    }
}T;
void add(int u,int v){
    edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void dfs(int u){
    dfn[u]=++ind;
    for(int i=0;fa[u][i];i++) 
        fa[u][i+1]=fa[fa[u][i]][i];
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==fa[u][0]) continue;
        fa[v][0]=u;
        dep[v]=dep[u]+1;
        dfs(v);
    }
    lst[u]=ind;
}
int jump(int u,int dis){
    for(int i=18;dis;i--){
        if(dis>=(1<<i)){
            dis-=(1<<i);
            u=fa[u][i];
        }
    }
    return u;
}
int LCA(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    u=jump(u,dep[u]-dep[v]);
    if(u==v) return u;
    for(int i=18;i>=0;i--) 
        if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
void solve(int l,int r,int st,int ed){
    if(st>ed) return;
    if(l==r){
        for(int i=st;i<=ed;i++) ans[pt[i].id]=rect[l].v;
        return;
    }
    int mid=(l+r)>>1,siz=0;
    for(int i=l;i<=mid;i++){
        line[++siz]=(Line){rect[i].xd,rect[i].yd,rect[i].yu,1,0};
        line[++siz]=(Line){rect[i].xu,rect[i].yd,rect[i].yu,-1,n+1};
    }
    for(int i=st;i<=ed;i++) 
        line[++siz]=(Line){pt[i].x,pt[i].y,0,0,i};
    sort(line+1,line+siz+1);
    for(int i=1;i<=siz;i++){
        if(st<=line[i].id&&line[i].id<=ed) sum[line[i].id]=T.query(line[i].yd);
        else T.modify(line[i].yd,line[i].yu,line[i].v);
    }
    int a=0,b=0;
    for(int i=st;i<=ed;i++){
        if(sum[i]>=pt[i].k) tmp1[++a]=pt[i];
        else tmp2[++b]=(Point){pt[i].x,pt[i].y,pt[i].k-sum[i],pt[i].id};
    }
    for(int i=st;i<=st+a-1;i++) pt[i]=tmp1[i-st+1];
    for(int i=st+a;i<=ed;i++) pt[i]=tmp2[i-st-a+1];
    solve(l,mid,st,st+a-1);
    solve(mid+1,r,st+a,ed);
}
int main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    dfs(1);
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        int u=LCA(a,b);
        if(dfn[a]>dfn[b]) swap(a,b);
        if(u!=a) 
            rect[++tot]=(Rectangle){dfn[a],lst[a],dfn[b],lst[b],c};
        else{
            int w=jump(b,dep[b]-dep[a]-1);
            rect[++tot]=(Rectangle){1,dfn[w]-1,dfn[b],lst[b],c};
            if(lst[w]<n) rect[++tot]=(Rectangle){dfn[b],lst[b],lst[w]+1,n,c};
        }
    }
    sort(rect+1,rect+tot+1);
    for(int i=1;i<=q;i++){
        int a,b,k;
        scanf("%d%d%d",&a,&b,&k);
        if(dfn[a]>dfn[b]) swap(a,b);
        pt[i]=(Point){dfn[a],dfn[b],k,i};
    }
    solve(1,tot,1,q);
    for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
    return 0;
}

根据提供的引用内容,你遇到的问题是在发送HTTP POST请求时收到了403 Forbidden的错误。这个错误通常表示你没有权限访问所请求的资源。 要解决这个问题,你可以采取以下步骤: 1. 首先,确保你的请求URL正确,并且你有权限访问该URL。你可以尝试在浏览器中直访问该URL,看看是否能够成功访问。 2. 如果你确定URL是正确的,并且你有权限访问,那么可能是你的请求中缺少了必要的身份验证信息。你可以检查你的请求头中是否包含了正确的身份验证信息,比如Token或用户名密码。 3. 另外,你还可以检查服务器端的配置,确保你的请求被正确地处理和授权。你可以查看服务器的日志,以了解更多关于403错误的详细信息。 综上所述,当你收到403 Forbidden错误时,你应该首先检查URL和权限,然后确保请求中包含了正确的身份验证信息。如果问题仍然存在,你可以进一步检查服务器端的配置和日志,以找出问题的根本原因。 #### 引用[.reference_title] - *1* [kubeadm init报错10248...(The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz‘ failed)](https://blog.csdn.net/weixin_45969972/article/details/123529966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)](https://blog.csdn.net/xsy29000/article/details/103181267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值