首页 > 其他分享 >CF-702-E-倍增

CF-702-E-倍增

时间:2024-01-17 14:24:01浏览次数:35  
标签:个点 int 边权 CF 702 vector 数组 倍增

702-E 题目大意

\(n\)个点,每个点有一条出边,边带权。给定整数\(k\)。求从每个节点出发经过\(k\)条边的路径上所有的边权和,以及最小的边权。


Solution

给定的图是基环树森林,从任意一个点出发无限走下去一定会进入环内。

倍增板子题,这里不详细解释什么是倍增数组,具体的可以网上自行学习。这里用到三个倍增数组:

  • \(to[i][j]\):从第\(i\)个点出发走\(2^j\)步到达的顶点。
  • \(sum[i][j]\):从第\(i\)个点出发走\(2^j\)步,路径上的边权和。
  • \(mn[i][j]\):第\(i\)个点出发走\(2^j\)步,路径上最小的边权。

倍增数组的构建,核心思路就是公式

\[2^{j}=2^{j-1}+2^{j-1} \]

以\(to\)数组为例,当前我们已将所有点走过\(2^{j-1}\)步的数组预处理完毕:

\[to[i][j]=to[to[i][j-1]][j-1] \]

从第\(i\)点出发先走\(2^{j-1}\)步到达\(to[i][j-1]\)再走\(2^{j-1}\)即到达目标点。

查询节点\(i\)经\(k\)条边后的边权和与最小边权:
由高到低枚举\(k\)的二进制位,如果\(k\)的第\(j\)位为\(1\),则从当前点跳到\(to[i][j]\),同时更新所求的路径和以及最小的边权。

时间复杂度\(O(nlogk)\)。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;

void solve(){
    int n;
    ll k;
    cin>>n>>k;
    int P=35;
    vector<vector<int>> to(n+1,vector<int>(P));
    vector<vector<ll>> sum(n+1,vector<ll>(P));
    vector<vector<int>> mn(n+1,vector<int>(P,1e9));
    for(int i=0;i<n;i++){
        int j;
        cin>>j;
        to[i][0]=j;
    }
    for(int i=0;i<n;i++){
        int w;
        cin>>w;
        sum[i][0]=mn[i][0]=w;
    }
    for(int j=1;j<P;j++){
        for(int i=0;i<n;i++){
            to[i][j]=to[to[i][j-1]][j-1];
            sum[i][j]=sum[i][j-1]+sum[to[i][j-1]][j-1];
            mn[i][j]=min(mn[i][j-1],mn[to[i][j-1]][j-1]);
        }
    }
    for(int i=0;i<n;i++){
        ll path_sum=0;
        int path_mn=1e9,x=i;
        for(int i=P-1;~i;i--){
            if(k&(1LL<<i)){
                path_sum+=sum[x][i];
                path_mn=min(path_mn,mn[x][i]);
                x=to[x][i];
            }
        }
        cout<<path_sum<<" "<<path_mn<<'\n';
    }
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

标签:个点,int,边权,CF,702,vector,数组,倍增
From: https://www.cnblogs.com/fengxue-K/p/17969925

相关文章

  • [CF1707E] Replace
    Replace题面翻译题目描述给定一个长为\(n\)的序列\(a_1,\ldots,a_n\),其中对于任意的\(i\)满足\(1\leqa_i\leqn\)。定义一个二元组函数如下:\[f((l,r))=(\min\{a_l,\ldots,a_r\},\max\{a_l,\ldots,a_r\})(l\leqr)\]你需要回答\(q\)次询问,每次给定\((l_i,r_i)\)......
  • CNCF大使预测:2024年云原生面临倦怠、离职及云成本精简
    本文由CNCF大使EricD.Schabell撰写,预测2024年云原生领域最可能发生的3大变化,并与其对云原生可观测性领域的见解结合。 关注云原生倦怠毫无疑问,在2023年中云原生可观测性领域的头号话题是倦怠。这涉及到每一个角色,从SREs、DevOps、工程师、开发人员到管理企业内云原生......
  • CF1919F2 Wine Factory (Hard Version)
    题意有\(n\)个桶,每个桶里有\(a_i\)单位水。每次查询按\(1,2...,n\)的顺序进行。当操作到桶\(i\)时,先将当前桶里的水取\(b_i\)加入答案。并将当前里的水全部流向\(i+1\),最多只能流\(c_i\)单位。每次修改\(a_p,b_p,c_p\)查询答案。Sol不难想到建模网络流......
  • CF1876D Lexichromatography 题解
    Problem-D-CodeforcesLexichromatography-洛谷先注意读题:对于所有的值\(k\),在这个序列的任意子区间\([l,r]\)中,值为\(k\)且为红色的位置数减去值为\(k\)且为蓝色的位置数的绝对值不超过\(1\)注意是任意子区间这说明什么?说明如果只有第二个条件,我......
  • CF607E Cross Sum
    首先考虑把定点置换到原点,则直线方程变为\(y+y_0=\dfraca{1000}(x+x_0)+\dfracb{1000}\)。令\(k=\dfraca{1000},c=\dfrac{ax_0+b}{1000}-y_0\),则有\(y=kx+c\)。考虑二分答案,找到一个最小的圆,使得圆内有至少\(m\)个交点,圆的半径\(r\)就是答案。......
  • CF610E
    简单题。想到怎么计数就结束了。重点就是怎么样计算循环次数。肯定是不能枚举一遍,双指针去数的。但是发现\(t\)有一个很好的性质:它是\([1,k]\)内字符的排列。说明每个字符在\(t\)中只会出现一次。然后发现,可以按照最长公共子序列那题类似的思路,根据\(t\)内字符的位置为......
  • 数论好题 CF900D
    前置推导令\(b_1=\frac{a_1}{x},b_2=\frac{a_2}{x},\dots,b_n=\frac{a_n}{x}\)。很显然\(b_i\)为整数,且\(b\)数组的全部元素互质,即\(gcd(b_1,b_2,b_3,\dots,b_n)=1\)。因为\[\sum_{i=1}^{n}a_i=y\]所以\[x\times\sum_{i=1}^{n}b_i=y\]\[\sum_{i=......
  • CF1921F Sum of Progression
    题目链接:CF一道经典的类型题,把这种类型的题拿出来单独说一下。注意到问题中涉及到需要维护\(a_{x+k\timesstep}\)这样的信息,这样的信息很难用树型结构维护,比较容易用块级结构维护,我们注意到其实是每次这种步长\(+step\)的信息很难维护,我们考虑一类特殊的分块:如果\(step\)......
  • 数论好题 CF900D
    前置推导令\(b_1=\frac{a_1}{x},b_2=\frac{a_2}{x},\dots,b_n=\frac{a_n}{x}\)。很显然\(b_i\)为整数,且\(b\)数组的全部元素互质,即\(gcd(b_1,b_2,b_3,\dots,b_n)=1\)。因为\[\sum_{i=1}^{n}a_i=y\]所以\[x\times\sum_{i=1}^{n}b_i=y\]\[\sum_{i=......
  • CF1437F Emotional Fishermen 题解
    题意:有\((n\le5000)\)个渔民,每个渔民钓了一条重\(a_i\)的鱼,渔民按任意顺序展示他们的鱼。若当前渔民的鱼的重量为\(x\),之前展示过的鱼的最大重量\(y\)。一个排列满足条件当且仅当对于每个\(x\),满足\(2y\lex\)或\(2x\ley\)。问有多少个排列满足条件,对\(998244353......