codeforces702E---倍增法求解,第一发

倍增法是著名的RMQ算法的思想基础。其中的倍增是为了得到二进制数字,。这样我们需要一个k的长度的数值,就是需要k的二进制的一些组合,同时,由于lgn的内存和lgn的搜索速度,都是可以接受的,同时2^N--->2^(N+1)可以通过维护转移来得到,也就是DP,这样就是一个完美无缺的解法,同时,如果可以适用于许多的问题。

上代码:

#include <algorithm>
#include <assert.h>
#include <complex>
#include <ctype.h>
#include <functional>
#include <iostream>
#include <limits.h>
#include <locale.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
//#include <unordered_set>
//#include <unordered_map>

#pragma warning(disable:4996)
using namespace std;

#define mp make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <ldb, ldb> pdd;

int IT_MAX = 1 << 21;
const int MOD = 1000000007;
const int INF = 1034567891;
const ll LL_INF = 1234567890123456789ll;
const db PI = 3.141592653589793238;
const ldb ERR = 1E-12;
vector <int> h[100010] ;
int gra[100010] ;
int weg[100010] ;
int vis[100010] ;
int d[100010][60] ;
ll sum[100010][60] ; /// 表示长度是2^n的i开始的最终的sum和
ll mam[100010][60] ; /// 表示长度是2^n的i开始的最终的max和
int cnt = 0 ;
#define mem(x ,y ) memset(x , y , sizeof(x))
int main() {
    ll n , m ;cin >> n >> m ;
    for(int i=0;i<n;i++){
        scanf("%d" ,gra+i) ;
    }
    for(int i=0;i<n;i++) scanf("%d" ,  weg+i) ;
    for(int i=0;i<n;i++){
        d[i][0]   = gra[i] ;
        sum[i][0] = weg[i] ;
        mam[i][0] = weg[i] ;
    }
    for(int i=1;i<60;i++){
        for(int j=0;j<n;j++){
            int tmp = d[j][i-1] ;
            d[j][i] = d[tmp][i-1] ;
            sum[j][i] = sum[j][i-1] + sum[tmp][i-1] ;
            mam[j][i] = min(mam[j][i-1] , mam[tmp][i-1]) ;
        }
    }
    for(int i=0;i<n;i++){
        ll k = m ;
        int tmp = i ;
        int cnt = 0 ;
        ll sss = 0 ;
        ll mmm = LL_INF ;
        while(k){
            if(k & 1){
                sss += sum[tmp][cnt] ;
                mmm = min(mmm , mam[tmp][cnt]) ;
                tmp = d[tmp][cnt] ;
            }
            cnt ++ ; k >>= 1 ;
        }
        printf("%I64d %I64d\n" , sss , mmm) ;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值