CF1392B 题解

题意翻译

给出一个长度为 n n n的序列 a a a以及一个 k k k,我们定义进行一次操作分以下两步:

d d d表示序列中的最大值
对于每个 i ∈ [ 1 , n ] i\in[1,n] i[1,n],将 a i a_i ai替换成 d − a i d-a_i dai
现在请你输出进行 k k k次操作后的序列。

思路

  1. 表面上是一个区间维护最后查询,可数据 1 < k < = 1 0 18 1<k<=10^{18} 1<k<=1018 O ( k ) ∗ 多 组 数 据 O(k)* 多组数据 O(k)一定不行
  2. 那让我们思考 O ( 1 ) O(1) O(1)做法:
    先模拟一下样例:
3
2 1
-199 192
5 19
5 -1 4 2 0
1 2
69

第一组:

[ 192 − ( − 199 ) , 192 − 192 ] − > [ 391 , 0 ] [192-(-199),192-192]->[391,0] [192(199),192192]>[391,0]

第二组:

[ 5 − 5 , 5 − ( − 1 ) , 5 − 4 , 5 − 2 , 5 − 0 ] − > [ 0 , 6 , 1 , 3 , 5 ] [5-5,5-(-1),5-4,5-2,5-0]->[0,6,1,3,5] [55,5(1),54,52,50]>[0,6,1,3,5]
[ 6 − 0 , 6 − 6 , 6 − 1 , 6 − 3 , 6 − 5 ] − > [ 6 , 0 , 5 , 3 , 1 ] [6-0,6-6,6-1,6-3,6-5]->[6,0,5,3,1] [60,66,61,63,65]>[6,0,5,3,1]
[ 6 − 6 , 6 − 0 , 6 − 5 , 6 − 3 , 6 − 1 ] − > [ 0 , 6 , 1 , 3 , 5 ] [6-6,6-0,6-5,6-3,6-1]->[0,6,1,3,5] [66,60,65,63,61]>[0,6,1,3,5]
[ 6 − 0 , 6 − 6 , 6 − 1 , 6 − 3 , 6 − 5 ] − > [ 6 , 0 , 5 , 3 , 1 ] [6-0,6-6,6-1,6-3,6-5]->[6,0,5,3,1] [60,66,61,63,65]>[6,0,5,3,1]

  • 到这里我们可以看到1次变换之后 d d d已经固定了 M a x ( a ) − M i n ( a ) Max(a)-Min(a) Max(a)Min(a),不懂的看下面:

1 [ a 1 , a 2 , a 3... , M a x , M i n ] [a1,a2,a3...,Max,Min] [a1,a2,a3...,Max,Min]//两数位置不定

2 [ M a x − a 1 , M a x − a 2...0 , M a x − M i n ] [Max-a1,Max-a2...0,Max-Min] [Maxa1,Maxa2...0,MaxMin]//x-y当x固定时,y越小值越大,所以Max-MIn就是最大的;

3 [ ( M a x − M i n ) − ( M a x − a 1 ) , ( M a x − M i n ) − ( M a x − a 2 ) . . . M a x − M i n , 0 ] [(Max-Min)-(Max-a1),(Max-Min)-(Max-a2)...Max-Min,0] [(MaxMin)(Maxa1),(MaxMin)(Maxa2)...MaxMin,0]

可以发现,原来的Max和Min现在一定都是一个是0,一个是最大值: M a x − M i n Max-Min MaxMin

代码实现

  1. 输入后找到 M a x Max Max M i n Min Min
  2. 如果 k m o d 2 = 1 k mod 2=1 kmod2=1输出 M a x − a i {Max-a_i} Maxai
  3. 否则输出 a i − M i n {a_i-Min} aiMin M a x − M i n − ( M a x − a i ) = − M i n + a i = a i − M i n Max-Min-(Max-a_i)=-Min+a_i=a_i-Min MaxMin(Maxai)=Min+ai=aiMin)
#include<bits/stdc++.h>
using namespace std;
int min(int a,int b){return a>b?b:a;}
int max(int a,int b){return a>b?a:b;}
int a[200039],N,T;
long long k;
int Max,Min;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%lld",&N,&k);
        Min=1000000000;Max=-1000000000;
        for(int i=1;i<=N;i++){
            scanf("%d",&a[i]);
            Min=min(a[i],Min);
            Max=max(a[i],Max);
        }
        if(k%2==1){
            for(int i=1;i<=N;i++)printf("%d ",Max-a[i]);
        }
        else{
            for(int i=1;i<=N;i++)printf("%d ",a[i]-Min);
        }
        printf("\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值