zoukankan      html  css  js  c++  java
  • 【树】【积累】Waterloo2019ICPC D.Deliveries (整除分块+树分块+括号序)

    题解:Waterloo2019ICPC D.Deliveries (整除分块+树分块+括号序)

    题目链接:cf Waterloo2019ICPC D.Deliveries

    题意:

    一棵 (N) 个顶点的带边权无根树,(Q) 个询问。每次询问 (S;F;T) ,表示从点 (S) 到点 (F) 用容量为 (T) 的电池前进,全程总共需要停下来多少次 。对于每个询问输出一行一个整数。

    电池每当用完时,必须立刻停下来充电,后才能继续前进;每到达一个顶点必须停下来一次,停下来的这一次也可以用来充电。起点和终点需要各算一次停止次数。

    时限:4s;空限:256MB。

    数据范围:(1le N,Qle100000) , (1le w,Tle20000)

    样例:

    input

    7 5
    1 2 1
    2 3 2
    2 4 3
    4 5 4
    4 6 5
    4 7 6
    3 7 2
    2 6 1
    5 7 3
    1 4 1
    3 7 1
    

    output

    7
    9
    5
    5
    12
    

    input

    4 3
    1 2 5
    2 3 10
    3 4 20
    1 4 20
    1 4 10
    1 4 5
    

    output

    4
    5
    8
    

    伪标程:(抄标程,改一下代码风格,加一些注释)

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=5e5+5;
    
    int head[maxn],to[maxn<<1],nxt[maxn<<1],cnt;
    inline void add(int u,int v){
        to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    }
    int din[maxn],dout[maxn],tnt,f[maxn][25];
    void dfs(int u,int fa)
    {
        din[u]=++tnt;f[u][0]=fa;
        for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];i;i=nxt[i])
            if(to[i]!=fa)dfs(to[i],u);
        dout[u]=++tnt;
    }
    inline bool upper(int u,int v){
        return din[u]<=din[v]&&dout[u]>=dout[v];
    }
    int LCA(int u,int v)
    {
        if(upper(u,v))return u;
        for(int i=20;i>=0;i--)
            if(!upper(f[u][i],v))u=f[u][i];
        return f[u][0];
    }
    struct EG{
        int u,v;
    }eg[maxn];
    const int MAXN=2e4+5;
    const int K=512;
    struct Qu{
        int u,v,id;
    };vector<Qu>qu[MAXN];
    int *C[maxn];
    int siz[maxn],dis[maxn],S[maxn],A[maxn];ll res[maxn];
    ll cal(int l,int r)
    {
        ll res=0;
        while(l<=r)
        {
            if(l%K==0&&l+K-1<=r){
                res+=S[l/K];l+=K;
            }
            else res+=A[l++];
        }
        return res;
    }
    int main()
    {
        int n,q,u,v,w;
        scanf("%d%d",&n,&q);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v);add(v,u);eg[i]={u,v};
            w--;
            dis[i]=w;
            for(int l=1,r;l<=w;l=r+1){
                siz[l]++;r=w/(w/l);
            }
            siz[w+1]++;
        }
        for(int i=0;i<MAXN;i++)C[i]=new int[siz[i]+1];
        mem(siz,0);
        for(int i=1;i<=n-1;i++)C[1][siz[1]++]=i;
        dfs(1,1);
        for(int i=1;i<=q;i++){
            scanf("%d%d%d",&u,&v,&w);
            qu[w].push_back({u,v,i});
        }
        for(int i=1;i<=n-1;i++)if(din[eg[i].u]>din[eg[i].v])swap(eg[i].u,eg[i].v);
        for(int c=1;c<MAXN;c++)//枚举T
        {
            for(int i=0;i<siz[c];i++)
            {
                int id=C[c][i];//边的id
                int val=dis[id]/c;
                if(val){
                    int cc=dis[id]/val+1;
                    /*
                     在区间cc=[c,dis/(dis/c)]这个区间内,
                     dis/cc的值是一样的,都是 (val=dis/c)+1
                     */
                    C[cc][siz[cc]++]=id;
                }
                val++;
                S[din[eg[id].v]/K]+=(val-A[din[eg[id].v]]);A[din[eg[id].v]]=val;
                S[dout[eg[id].v]/K]+=(-val-A[dout[eg[id].v]]);A[dout[eg[id].v]]=-val;
                /*
                 此时 在块[id/K]里边更新块值和, 同时记录单点答案
                 在求值时,当[l,r]的距离大于K时,不断加上块和,
                 直到[l,r]距离小于K,再遍历累加单点值
                 */
            }
            delete[] C[c];
            for(Qu qq:qu[c]){
                u=LCA(qq.u,qq.v);
                res[qq.id]=cal(din[u]+1,din[qq.u])+cal(din[u]+1,din[qq.v]);
            }
        }
        for(int i=1;i<=q;i++)printf("%lld
    ",res[i]+1);
    }
    


    叨叨:

    T^T 这道题的做法对我来说真的是太难想到了。看标程的时候都 险些看不懂。

  • 相关阅读:
    python-----贴图 和 报错:OSError: image file is truncated (8 bytes not processed)的处理
    springboot集成RabbitMQ
    MySQL数据库设计规范
    腾讯云COS对象存储
    腾讯云OCR图片文字识别
    java基础之 java注释
    centos7下自动备份mysql数据库
    nginx配置ssl证书
    java基础之 控制语句
    js -- 操作sqlite数据库
  • 原文地址:https://www.cnblogs.com/kkkek/p/13661653.html
Copyright © 2011-2022 走看看