zoukankan      html  css  js  c++  java
  • 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("
    ");
    }
    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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    BZOJ1033:[ZJOI2008]杀蚂蚁antbuster(模拟)
    BZOJ4001:[TJOI2015]概率论(卡特兰数,概率期望)
    BZOJ1820:[JSOI2010]Express Service 快递服务(DP)
    BZOJ4066:简单题(K-D Tree)
    2110. [NOIP2015普及]金币
    73. 找最佳通路
    cogs 7. 通信线路
    codevs 3295 落单的数
    151. [USACO Dec07] 建造路径
    必备算法之二叉树的相关操作
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14118510.html
Copyright © 2011-2022 走看看