IncDec序列 差分数组

本文介绍了一种使用差分数组解决特定数组转换问题的高效算法。通过将原数组转化为差分数组,我们能够快速计算出将数组所有元素变为相同值所需的最小操作次数,并确定可能的不同操作方案数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

差分数组实例

题目链接请点击此处

大致讲一下题意,给一个数组,让我用最少的次数将这个数组重置为相同的值,也就是数组内所有数字大小必须相同,而每一次操作仅允许对一个区间进行+1或者-1的操作。
区间修改,而且是修改相同的值,就让我想到了差分数组,差分数组不熟悉的请点击让每一个值都相同其实就是让差分数组从第二个开始都为0!当从第二个开始都为0时那么整个数组都会变成第一个值的大小。
那么首先就先将这一题所给原数组转化为差分数组,然后计算从第二个位置开始数组元素全部转化为0的步数。这里可以逆向思考,从0恢复到原数组元素的步数就是题目所问的最少步数,而恢复原数组的最快步数就是ans=max(正数之和,负数之和的绝对值);解释一下:因为差分数组每一次变化都会产生一对相反数,而那么我只需要注意绝对值大的就行了,至于多出来的正数或者负数其实是可以放在最后的也就是n+1或者放到第一个位置(这里一开始没有运算!)的位置。至此步数就解决了!!!
现在解决有多少种的问题:首先我之前说了一句,在经过最少次数变化以后,整个数组都会变成第一个数字的值,那么种类个数只需要考虑一下第一个数字有多少种可能就行了!在之前说过可以放第一个位置,为什么呢,因为放到这里可以改变整个数组的值,也就是中间可以放多少个,就可以改变多少次,所以答案就是(正数-负数)的绝对值+1

#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
    int a[100009],n,m,i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    int c[100009],ko=a[1];
    for(i=2;i<=n;i++)
    {
        c[i]=a[i]-ko;
        ko=a[i];
    }//差分数组
    long long sum2=0,sum1=0,maxx=0,minn=c[1];
    for(i=2;i<=n;i++)
    {
        if(c[i]>0) sum1+=c[i];
        else sum2-=c[i];
    }
    printf("%lld\n",max(sum1,sum2));
    printf("%lld\n",abs(sum1-sum2)+1);
}

Traceback (most recent call last): File "C:\Users\Kanyun\Desktop\FEDformer\run.py", line 153, in <module> exp.train(setting, args.root_path, args.data_path) File "C:\Users\Kanyun\Desktop\FEDformer\exp\exp_main.py", line 161, in train outputs = self.model(batch_x, dec_inp) # 修改为只传入 batch_x 和 dec_inp File "C:\Users\Kanyun\AppData\Local\Programs\Python\Python37\lib\site-packages\torch\nn\modules\module.py", line 1194, in _call_impl return forward_call(*input, **kwargs) File "C:\Users\Kanyun\Desktop\FEDformer\models\Informer.py", line 76, in forward dec_out = self.decoder(dec_out, enc_out, x_mask=dec_self_mask, cross_mask=dec_enc_mask) File "C:\Users\Kanyun\AppData\Local\Programs\Python\Python37\lib\site-packages\torch\nn\modules\module.py", line 1194, in _call_impl return forward_call(*input, **kwargs) File "C:\Users\Kanyun\Desktop\FEDformer\layers\Transformer_EncDec.py", line 124, in forward x = layer(x, cross, x_mask=x_mask, cross_mask=cross_mask) File "C:\Users\Kanyun\AppData\Local\Programs\Python\Python37\lib\site-packages\torch\nn\modules\module.py", line 1194, in _call_impl return forward_call(*input, **kwargs) File "C:\Users\Kanyun\Desktop\FEDformer\layers\Transformer_EncDec.py", line 99, in forward attn_mask=x_mask File "C:\Users\Kanyun\AppData\Local\Programs\Python\Python37\lib\site-packages\torch\nn\modules\module.py", line 1194, in _call_impl return forward_call(*input, **kwargs) File "C:\Users\Kanyun\Desktop\FEDformer\layers\SelfAttention_Family.py", line 177, in forward attn_mask File "C:\Users\Kanyun\AppData\Local\Programs\Python\Python37\lib\site-packages\torch\nn\modules\module.py", line 1194, in _call_impl return forward_call(*input, **kwargs) File "C:\Users\Kanyun\Desktop\FEDformer\layers\SelfAttention_Family.py", line 135, in forward scores_top, index = self._prob_QK(queries, keys, sample_k=U_part, n_top=u) File "C:\Users\Kanyun\Desktop\FEDformer\layers\SelfAttention_Family.py", line 76, in _prob_QK M = Q_K_sample.max(-1)[0] - torch.div(Q_K_sample.sum(-1), L_K) IndexError: max(): Expected reduction dim 2 to have non-zero size. Process finished with exit code 1 根据以上报错修改对应代码: def _prob_QK(self, Q, K, sample_k, n_top): B, H, L_K, E = K.shape _, _, L_Q, _ = Q.shape K_expand = K.unsqueeze(-3).expand(B, H, L_Q, L_K, E) index_sample = torch.randint(L_K, (L_Q, sample_k)) K_sample = K_expand[:, :, torch.arange(L_Q).unsqueeze(1), index_sample, :] Q_K_sample = torch.matmul(Q.unsqueeze(-2), K_sample.transpose(-2, -1)).squeeze() M = Q_K_sample.max(-1)[0] - torch.div(Q_K_sample.sum(-1), L_K) M_top = M.topk(n_top, sorted=False)[1] Q_reduce = Q[torch.arange(B)[:, None, None], torch.arange(H)[None, :, None], M_top, :] Q_K = torch.matmul(Q_reduce, K.transpose(-2, -1)) # factor*ln(L_q)*L_k return Q_K, M_top
06-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值