CF587C Duff in the Army(树链剖分+线段树)

这题的题意告诉你,每次询问不超过10,说明我们只需要维护前10个即可,这样的话维护的大小就不多

因此可以直接树链剖分+线段树来做,但是还有个问题,不能直接套一个含log的数据结构进去,因为这样复杂度会多一个log,我之前用的set超时了

因此还是使用使用vector直接归并数组来做

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int h[N],ne[N],e[N],idx;
int dfn[N],ins[N],low[N],times;
int depth[N],fa[N],id[N],top[N],son[N],sz[N];
int n,m,q;
vector<int> num[N];
struct arr{
    int q[10],len;
    int size(){
        return len;
    }
    void push_back(int x){
        q[len++]=x;
    }
    void clear(){
        for(int i=0;i<10;i++){
            q[i]=0;
        }
        len=0;
    }
};
struct node{
    int l,r;
    arr s;
}tr[N<<2];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int f){
    sz[u]=1;
    int i;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==f)
            continue;
        fa[j]=u;
        depth[j]=depth[u]+1;
        dfs(j,u);
        sz[u]+=sz[j];
        if(sz[j]>sz[son[u]])
            son[u]=j;
    }
}
void dfs1(int u,int x){
    dfn[u]=++times;
    id[times]=u;
    top[u]=x;
    if(!son[u])
        return;
    dfs1(son[u],x);
    int i;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa[u]||j==son[u])
            continue;
        dfs1(j,j);
    }
}
arr merge(arr a,arr b){
    arr d;
    d.clear();
    int i=0,j=0;
    while(j<b.size()&&i<a.size()&&d.size()<10){
        if(a.q[i]<b.q[j])
            d.push_back(a.q[i++]);
        else
            d.push_back(b.q[j++]);
    }
    while(j<b.size()&&d.size()<10)
        d.push_back(b.q[j++]);
    while(i<a.size()&&d.size()<10)
        d.push_back(a.q[i++]);
    return d;
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
        int i;
        for(auto x:num[l]){
            tr[u].s.push_back(x);
            if((int)tr[u].s.size()==10)
                break;
        }
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        tr[u].s=merge(tr[u<<1].s,tr[u<<1|1].s);
    }
}
arr q1;
void query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        q1=merge(q1,tr[u].s);
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid){
        query(u<<1,l,r);
    }
    if(r>mid)
        query(u<<1|1,l,r);
}
void querypath(int x,int y,int z){
    q1.clear();
    while(top[x]!=top[y]){
        if(depth[top[x]]<depth[top[y]])
            swap(x,y);
        query(1,dfn[top[x]],dfn[x]);
        x=fa[top[x]];
    }
    if(depth[x]>depth[y])
        swap(x,y);
    query(1,dfn[x],dfn[y]);
    int k=min((int)q1.size(),z);
    printf("%d ",k);
    for(int i=0;i<k;i++){
        printf("%d ",q1.q[i]);
    }
    printf("\n");
}
int main(){
    //ios::sync_with_stdio(false);
    memset(h,-1,sizeof h);
    cin>>n>>m>>q;
    int i;
    for(i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    depth[1]=1;
    dfs(1,-1);
    dfs1(1,1);
    for(i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        num[dfn[x]].push_back(i);
    }
    build(1,1,n);
    while(q--){
        int u,v,a;
        scanf("%d%d%d",&u,&v,&a);
        querypath(u,v,a);
    }
}
View Code

 

posted @ 2020-12-11 08:37  朝暮不思  阅读(74)  评论(0编辑  收藏  举报