zoukankan      html  css  js  c++  java
  • CodeForces 702E Analysis of Pathes in Functional Graph

    倍增预处理。

    先看一下这张图的结构,因为出度都是$1$,所以路径是唯一的,又因为每个点都有出度,所以必然有环,也就是一直可以走下去。

    接下来我们需要记录一些值便于询问:

    设$t[i][j]$表示从$i$节点出发,走了${2^j}$步之后,到达的节点编号为$t[i][j]$。

    设$s[i][j]$表示从$i$节点出发,走了${2^j}$步之后,路径上的权值和为$s[i][j]$。

    设$m[i][j]$表示从$i$节点出发,走了${2^j}$步之后,路径上的权值最小值为$m[i][j]$。

    像$RMQ$一样,我们可以$dp$预处理出所有的$t[i][j]$,$s[i][j]$,$m[i][j]$。

    然后每次询问,只要沿着路从起点找到终点就可以了。单次询问的复杂度为$O(log n)$,可以理解为$k$的二进制上哪几位是$1$。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
        while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar();  }
    }
    
    const int maxn=100010;
    int n,f[maxn],w[maxn];
    LL t[maxn][45],s[maxn][45],m[maxn][45],k;
    LL b[maxn];
    
    int main()
    {
        b[0]=1; for(int i=1;i<=40;i++) b[i]=2*b[i-1];
        scanf("%d%lld",&n,&k);
        for(int i=0;i<n;i++) scanf("%d",&f[i]);
        for(int i=0;i<n;i++) scanf("%lld",&w[i]);
        for(int i=0;i<n;i++) m[i][0]=s[i][0]=w[i], t[i][0]=f[i];
    
        for(int i=1;i<=40;i++)
        {
            for(int j=0;j<n;j++)
            {
                m[j][i]=min(m[j][i-1],m[t[j][i-1]][i-1]);
                s[j][i]=s[j][i-1]+s[t[j][i-1]][i-1];
                t[j][i]=t[t[j][i-1]][i-1];
            }
        }
    
        for(int i=0;i<n;i++)
        {
            LL sum=0,Min=w[i]; int tmp=i;
            for(int j=40;j>=0;j--)
            {
                if(k&((LL)1<<(LL)j))
                {
                    int pos=j;
                    sum=sum+s[tmp][pos];
                    Min=min(Min,m[tmp][pos]);
                    tmp=t[tmp][pos];
                }
            }
    
            printf("%lld %lld
    ",sum,Min);
        }
        return  0;
    }
  • 相关阅读:
    Spring Cloud 接口契约测试
    看我玩弄千万日志于股掌
    从哲学层面浅谈计算机学习方法论
    一切互联网优势都是效率优势,一切竞争最终都是效率之争
    Arduino--蜂鸣器
    Arduino--光感应模块--模拟输入
    Arduino---按钮
    Arduino--PWM引脚
    Arduino专用绘图软件Fritzing
    点亮LED灯
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5804539.html
Copyright © 2011-2022 走看看