1 条题解
-
0
//对a上区间l - r上加减一个数 //对差分数组为b[l] += 1 / -= 1 // b[r + 1] -= 1 / += 1 //差分数组的定义 //b[1] = a[1] //b[2] = a[2] - a[1] //b[3] = a[3] - a[2] // .... // .... //b[n] = a[n] - a[n - 1] //如果a数组的所有数相同 //b[1] = a[1] //b[2] - b[n] 都=0 //那么原问题就变成了 //1.如果把一个差分数组b中b[2] - b[n]都变成0,且输出最少次数(最少,意味着可能贪心) //注意:此时b[1]可以是任意值,b[n + 1]也可以是任意值 //2.在1的基础上,b[1]有多少种可能 //对a的1-n区间内进行+1-1操作 //可以映射为对b的1-n+1区间进行+1-1操作(只不过a数组是一个个+1-1,b数组是对l和r+1两个点进行+1-1) //可以分成下面四种情况(L表示a中的左端点,R表示a中的右端点) //1. 2 <= L <= R <= n - 1 //此时对应到b数组的操作范围为2~n(因为b是对r+1进行操作,所以总比a的R多1) //那对应到差分操作,我们可以把b中2~n任意两个数进行+1-1,其中一个+1,另一个-1 //2. L == 1,R <= n - 1 //此时对应到b数组的操作范围为1~n //并且b[1] 要么+1要么-1, 另一个在2~n范围内的数也是要么+1要么-1 //3. 2 <= L,R == n //此时对应到b数组的操作范围为2~n+1 //并且b[n + 1] 要么+1要么-1,另一个在2~n范围内的数也是要么+1要么-1 //4. L == 1,R == n //对应b数组中1~n+1范围,整体+1-1无意义 //由于1情况可以同时把两个数一个+1一个-1 //基于贪心思想,先使用操作1 //操作1可以使用几次? //当b的2~n中如果不为0的数有大于0的也有小于0的,就可以用操作1 //因此操作1最多可以用min(p, q)次,(p为b(2~n范围)中所有大于0的数之和,q为所有小于0的数之和) //剩下一些要么大于0要么小于0的数,可以用操作2或3,用的次数为abs(p - q)次 //所有最少操作次数为min(p, q) + abs(p - q)次 //问题二:b[1]有几种可能? //在操作2里b[1]会被+1-1 //所有决定b[1]的值的操作为操作2 //操作2可以用几次就有多少种取值(因为最后abs(p - q)次操作时,剩下的数要么正要么负,所有操作23的目的是把正数或负数-1或+1变成0,所有最后的操作23一定都是+1或都是-1) //最后有abs(p - q)次操作,操作2可以用0,1....abs(p - q)次 //所有答案是abs(p - q) + 1 #include<bits/stdc++.h> using namespace std; const int N=100010; int a[N],b[N]; typedef long long LL; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=n;i++) { b[i]=a[i]-a[i-1]; } LL p=0,q=0; for(int i=2;i<=n;i++) { if(b[i]>0) { p+=b[i]; } else { q-=b[i]; } } cout<<max(p,q)<<endl; cout<<abs(p-q)+1<<endl; return 0; }
- 1
信息
- ID
- 1427
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 3
- 上传者