Codeforces Round #775 (Div. 2) ABCD题解

A. Game

题意
n 个 只 包 含 0 和 1 的 数 组 , 你 一 开 始 在 a [ 1 ] 位 置 , 求 走 到 a [ n ] 位 置 的 最 小 代 价 n个只包含0和1的数组,你一开始在a[1]位置,求走到a[n]位置的最小代价 n01,a[1]a[n]
如 果 a [ i ] = a [ i + 1 ] = 1 , 你 可 以 从 i 走 到 i + 1 , 代 价 为 0 如果a[i]=a[i+1]=1,你可以从i走到i+1,代价为0 a[i]=a[i+1]=1,ii+1,0
如 果 a [ i ] = a [ j ] = 1 [ i < j ] , 你 可 以 从 i 走 到 j , 代 价 为 j − i , 只 能 走 一 次 如果a[i]=a[j]=1[i<j],你可以从i走到j,代价为j-i,只能走一次 a[i]=a[j]=1[i<j],ij,ji,
思路
因 为 第 二 种 走 法 只 能 走 一 次 因为第二种走法只能走一次
所 以 找 到 第 一 个 连 续 的 一 的 最 后 一 个 位 置 L 所以找到第一个连续的一的最后一个位置L L
和 最 后 一 个 连 续 的 一 的 第 一 个 位 置 R 和最后一个连续的一的第一个位置R R
答 案 即 为 R − L 答案即为R-L RL
时间复杂度 O n On On

int n ;
int a[N] ;
 
signed main()
{
    cf
    {
        cin >> n ;
        fer(i,1,n) sf(a[i]) ;
        
        int l = -1 , r = -1 ;
        fer(i,1,n)
        {
            if(!a[i]) 
            {
                l = i - 1 ;
                break ;
            }
        }
        der(i,n,1)
        {
            if(!a[i])
            {
                r = i + 1 ;
                break ;
            }
        }
        
        de(r - l) ;
    }
    return 0 ;
}

B. Game of Ball Passing

题意
给 你 一 个 n 个 数 的 数 组 , a [ i ] 表 示 i 这 个 人 传 了 a [ i ] 次 球 给你一个n个数的数组,a[i]表示i这个人传了a[i]次球 n,a[i]ia[i]
现 在 问 你 进 行 了 最 少 多 少 次 传 球 使 得 所 有 人 都 可 以 传 完 现在问你进行了最少多少次传球使得所有人都可以传完 使
每 次 传 球 从 任 意 一 个 人 开 始 , 只 要 传 给 除 他 之 外 的 人 即 可 每次传球从任意一个人开始,只要传给除他之外的人即可 ,
思路
把 每 次 传 球 转 化 一 下 把每次传球转化一下
等 价 于 首 先 选 一 个 i , 使 a [ i ] − 1 等价于首先选一个i,使a[i]-1 i使a[i]1
然 后 在 任 意 选 2 个 不 同 的 下 标 i , j , 使 a [ i ] − 1 , a [ j ] − 1 , 可 以 进 行 无 数 次 然后在任意选2个不同的下标i,j,使a[i]-1,a[j]-1,可以进行无数次 2i,j,使a[i]1,a[j]1,

不 考 虑 首 先 选 一 个 i , 使 a [ i ] − 1 的 情 况 下 不考虑首先选一个i,使a[i]-1的情况下 i使a[i]1
记 录 一 下 数 组 总 和 s u m 和 数 组 最 大 值 m a x v 记录一下数组总和sum和数组最大值maxv summaxv
如 果 s u m − m a x v > = m a x v 如果sum-maxv>=maxv summaxv>=maxv
说 明 一 次 传 球 即 可 说明一次传球即可

考 虑 首 先 选 一 个 i , 使 a [ i ] − 1 的 情 况 下 考虑首先选一个i,使a[i]-1的情况下 i使a[i]1
那 我 们 二 分 进 行 了 多 少 次 传 球 m i d 那我们二分进行了多少次传球mid mid
如 果 m i d 次 可 以 传 球 成 功 , 说 明 m i d 可 以 变 小 如果mid次可以传球成功,说明mid可以变小 mid,mid
否 则 m i d 变 大 否则mid变大 mid

m i d 次 传 球 , 等 价 于 你 可 以 先 进 行 m i d 次 选 一 个 i , 使 a [ i ] − 1 mid次传球,等价于你可以先进行mid次选一个i,使a[i]-1 mid,midi使a[i]1
然 后 在 任 意 选 2 个 不 同 的 下 标 i , j , 使 a [ i ] − 1 , a [ j ] − 1 , 可 以 进 行 无 数 次 然后在任意选2个不同的下标i,j,使a[i]-1,a[j]-1,可以进行无数次 2i,j,使a[i]1,a[j]1,

即 s u m − m a x v > = m a x v − m i d 即 可 即sum-maxv>=maxv-mid即可 summaxv>=maxvmid

时间复杂度 O n On On

int n ;
int a[N] ;
int s , v ;
 
int get(int mid)
{
    if(s - v >= v - mid) return 1 ;
    
    return 0 ;
}
 
signed main()
{
    cf
    {
        cin >> n ;
        fer(i,1,n) sf(a[i]) ;
        
        s = 0 , v = 0 ;
        fer(i,1,n) s += a[i] , v = max(v , a[i]) ;
        
        if(!v)
        {
            puts("0") ;
            continue ;
        }
        
        int l = 1 , r = 1e10 ;
        while(l < r)
        {
            int mid = l + r >> 1 ;
            if(get(mid)) r = mid ;
            else l = mid + 1 ;
        }
        
        de(l) ;
    }
    return 0 ;
}

C. Weird Sum

题意
给 你 一 个 n ∗ m 的 方 格 , 每 个 方 格 c [ i ] [ j ] 都 有 一 个 颜 色 k , 求 给你一个n*m的方格,每个方格c[i][j]都有一个颜色k,求 nm,c[i][j]k,
∑ k = 1 1 e 5 ∑ x 1 = 1 n ∑ y 1 = 1 m ∑ x 2 = i + 1 n ∑ y 2 = j + 1 m ( ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ ) ∗ [ c [ x 1 ] [ y 1 ] = k 且 c [ x 2 ] [ y 2 ] = k ] \sum_{k=1}^{1e5}{\sum_{x1=1}^{n}\sum_{y1=1}^{m}\sum_{x2=i+1}^{n}\sum_{y2=j+1}^{m}{(|x1-x2|+|y1-y2|)}}*[ c[x1][y1]=k且c[x2][y2]=k ] k=11e5x1=1ny1=1mx2=i+1ny2=j+1m(x1x2+y1y2)[c[x1][y1]=kc[x2][y2]=k]
思路
首 先 ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ 可 以 分 开 算 首先|x1-x2|+|y1-y2|可以分开算 x1x2+y1y2
所 以 我 们 可 以 预 处 理 所 有 颜 色 的 不 同 的 横 坐 标 和 纵 坐 标 所以我们可以预处理所有颜色的不同的横坐标和纵坐标

现 在 问 题 等 价 于 对 于 任 意 一 个 序 列 现在问题等价于对于任意一个序列
a 1 a_1 a1 a 2 a_2 a2 a n a_n an
求 所 有 不 同 颜 色 的 ∑ i = 1 n ∑ j = i + 1 n ∣ a [ i ] − a [ j ] ∣ 求所有不同颜色的\sum_{i=1}^{n}{\sum_{j=i+1}^{n}|a[i]-a[j]|} i=1nj=i+1na[i]a[j]

首 先 将 数 组 排 序 之 后 首先将数组排序之后
因 为 ∑ i = 1 n ∑ j = i + 1 n ∣ a [ i ] − a [ j ] ∣ = ∑ i = 1 n ∑ j = 1 i − 1 ∣ a [ i ] − a [ j ] ∣ 因为\sum_{i=1}^{n}{\sum_{j=i+1}^{n}|a[i]-a[j]|}=\sum_{i=1}^{n}{\sum_{j=1}^{i-1}|a[i]-a[j]|} i=1nj=i+1na[i]a[j]=i=1nj=1i1a[i]a[j]
所 以 记 录 前 缀 和 直 接 加 即 可 所以记录前缀和直接加即可

时间复杂度 O n m l o g n m Onmlognm Onmlognm

int n , m ;
vector<int> g[N] ;
int res ;
 
void solve(vector<int> &v)
{
    sort(all(v)) ;
    int s = 0 ;
    for(int i = 0 ; i < sz(v) ; i ++)
    {
        res += v[i] * i - s ;
        s += v[i] ;
    }
}
 
signed main()
{
    cin >> n >> m ;
    
    vector<vector<int>> a(n + 1 , vector<int>(m + 1 , 0)) ;
    
    fer(i,1,n)
        fer(j,1,m)
        {
            sf(a[i][j]) ;
            g[a[i][j] * 2].pb(i) ;
            g[a[i][j] * 2 + 1].pb(j) ;
        }
        
    fer(i,1,2e5 + 10)
    {
        if(g[i].size())
            solve(g[i]) ;
    }
    
    de(res) ;
    return 0 ;
}

D. Integral Array

题意
给 你 一 个 n 个 数 的 数 组 , 如 果 数 组 中 没 有 出 现 a [ j ] / a [ i ] , [ a [ j ] > = a [ i ] , 1 < = i , j < = n ] 给你一个n个数的数组,如果数组中没有出现a[j]/a[i],[a[j]>=a[i],1<=i,j<=n] n,a[j]/a[i],[a[j]>=a[i],1<=i,j<=n]
输 出 N o 输出No No
否 则 输 出 Y e s 否则输出Yes Yes
思路
对 于 数 组 中 的 每 个 数 , 我 们 可 以 枚 举 它 的 倍 数 对于数组中的每个数,我们可以枚举它的倍数 ,
假 设 对 于 i 这 个 数 , 它 的 倍 数 为 j 假设对于i这个数,它的倍数为j i,j
那 么 区 间 [ i ∗ j , i ∗ j + i − 1 ] 中 的 任 何 一 个 数 x / i = j 那么区间[i*j,i*j+i-1]中的任何一个数x/i=j [ij,ij+i1]x/i=j
所 以 如 果 i 这 个 数 和 x 这 个 数 都 同 时 出 现 过 的 话 , 那 么 j 也 必 须 出 现 所以如果i这个数和x这个数都同时出现过的话,那么j也必须出现 ix,j
如 果 j 没 有 出 现 过 的 话 , 直 接 输 出 N o 即 可 如果j没有出现过的话,直接输出No即可 j,No

时间复杂度 时 间 复 杂 度 : n / 1 + n / 2 + . . . . . + n / n ≈ n l o g n 时间复杂度:n/1+n/2+.....+n/n \approx nlogn :n/1+n/2+.....+n/nnlogn

int n , m ;
int a[N] ;
int cnt[N] ;
int tt[N] ;
int cc[N] ;
 
signed main()
{
    cf
    {
        cin >> n >> m ;
        fer(i,0,m * 2 + 10) cnt[i] = 0 , cc[i] = 0  ;
        fer(i,1,n) scanf("%d",&a[i]) , cnt[a[i]] = 1 , cc[a[i]] = 1;
        fer(i,1,m * 2 + 10) cnt[i] += cnt[i - 1] ;
        
        int f1 = 0 ;
        for(int i = 1 ; i <= m ; i ++)
        {   if(cc[i])
            for(int j = 1 ; j * i <= m ; j ++)
            {
                int l = j * i , r = j * i + i - 1 ;
                if(cnt[r] - cnt[l - 1])
                {
                    if(!cc[j]) f1 = 1 ;
                }
            }
        }
        
        if(f1) puts("No") ;
        else puts("Yes") ;
    }
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值