题目链接
题意:给定一个原数组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是特殊数组,并且它做了多少次特殊操作。
发现这两个操作特别熟悉,其实就是一个差分的操作。
将b
和ci
看成差分数组,设b
对应的原数组(前缀和数组)为a
,那么ci
的两种操作就可以看为:
- 普通操作:在
a
数组上i-1
位置+1
,在a
数组的j
位置上-1
。 - 特殊操作:在
a
数组上i-1
位置+1
,在a
数组的j
和j+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;
}
}