「思维+差分」CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) D. Magical Array Solution
「思维+差分」CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) D. Magical Array Solution

「思维+差分」CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) D. Magical Array Solution

题目链接

题意:给定一个原数组b,和n个初始值和b一样的数组ci,选择一个ci作为特殊数组,对于普通数组,可以选择i,j让ci[i]和ci[j]减一,ci[i-1],c[j+1]加一;对于特殊数组,可以选择i,j让ci[i]和ci[j]减一,ci[i-1],c[j+2]加一。(i<j)。每个数组最少做一次操作。操作完后删去b。给出操作完的n个数组ci,问哪个ci是特殊数组,并且它做了多少次特殊操作。

发现这两个操作特别熟悉,其实就是一个差分的操作。

bci看成差分数组,设b对应的原数组(前缀和数组)为a,那么ci的两种操作就可以看为:

  • 普通操作:在a数组上i-1位置+1,在a数组的j位置上-1
  • 特殊操作:在a数组上i-1位置+1,在a数组的jj+1位置上-1

然后可以发现,普通操作对于原数组a的总和值是不会改变的,特殊操作会使得原数组a的总和值-1。(普通数组的前缀和数组的和是一致的。)

所以对所有ci求前缀和数组,再求和,特殊数组所求出来的值小于普通数组求出来的值,并且差值就是特殊数组的操作数量。

#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace IO{
    #define I inline
    I char tc(){static char tr[10000],*A=tr,*B=tr;return A==B&&(B=(A=tr)+fread(tr,1,10000,stdin),A==B)?EOF:*A++;}
    I void read(int &x){char c;for(;(c=tc())<48||c>57;);for(x=c-'0';(c=tc())>47&&c<58;x=(x<<1)+(x<<3)+c-'0');}
    // I void read(int &x){scanf("%d",&x);}
    #undef I
}using namespace IO;

const int N = 1e5+5;

int T,n,m,sum[N];

signed main(){
    for(read(T);T;--T){
        read(n),read(m);
        for(int i=1;i<=n;++i){
            for(int j=1,tot=0,x;j<=m;++j)read(x),tot+=x,sum[i]+=tot;
        }
        int mi=1;
        for(int i=2;i<=n;++i)if(sum[mi]>sum[i])mi=i;
        printf("%lld %lld\n",mi,sum[mi==n?1:n]-sum[mi]);
        for(int i=1;i<=n;++i)sum[i]=0;
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注