这道D题是纯粹的暴力?——离经叛道的思维题
这道D题是纯粹的暴力?——离经叛道的思维题
这次的标题并没有夸张,#808 的\(div2 D\)确确实实的是一道暴力题,当然,这是在将这个问题一次又一次的剖析之后,剩下只需要暴力就能做,因此成其为离经叛道的思维题。
题目描述
给定数组\(A(n)\),每次都需要对\(A\)做一次差分,即为\(A_i=A_{i+1}-A_i\),在差分之后进行排序,保证\(A\)不为负数,每次差分都会使得\(A\)减少一个元素,直到\(A\)只剩下一个元素停止,求该元素是多少?
- \(n (2≤n≤10^5)\)
- $a_1,a_2,…,a_n (0≤a_1≤…≤a_n≤5⋅10^5) $
input
5
3
1 10 100
4
4 8 9 13
5
0 0 0 8 13
6
2 4 8 16 32 64
7
0 0 0 0 0 0 0
output
81
3
1
2
0
In the first test case, \(a=[1,10,100]\) at first. After the first operation,$ a=sort([10−1,100−10])=[9,90]$. After the second operation, \(a=sort([90−9])=[81]\).
In the second test case,\(a=[4,8,9,13]\) at first. After the first operation, \(a=sort([8−4,9−8,13−9])=[1,4,4]\). After the second operation, \(a=sort([4−1,4−4])=[0,3]\). After the last operation, \(a=sort([3−0])=[3]\).
题目解析
最暴力的方法,无非就是每次做完差分再重新排序,时间复杂度达到了\(O(N^2logN)\)。
该如何暴力呢?既然是暴力,那就需要从差分这个操作“偷”时间。我们注意到\(a_i\)的取值范围是很有意思的,最大值为\(5e5\),也就是说,\(a\)数组在操作过程中一定会产生大量的重复数字,而一旦产生重复数字,就会产生\(0\)。(过程可以参考求导,\(f\)、\(f'\)、\(f''\)……会不断逼近\(0\))
既然我们已经先知道会产生大量的\(0\)了,那就可以对\(0\)进行特殊处理了。不难得到,每次操作,都只会让\(0\)减少一个,因此,我们可以对\(0\)进行单独的计数,操作结束后再放进去一个\(0\)即可。
如此简单!这道题有点像离经叛道的bebop了,更加强调思维性。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int tc;
cin >> tc;
while(tc--) {
int n;
cin >> n;
vector<ll>a(n);
for(auto &i:a)
cin >> i;
int zero = 0;
while(a.size() > 1) {
vector<ll>b;
for(int i = 1 ; i < a.size() ; i++ ) {
ll t = a[i]-a[i-1];
if(t)
b.push_back(t);
else zero++;
}
if(zero)
b.push_back(0),zero--;
sort(b.begin(),b.end());
a=b;
}
if(a.size())
cout << a[0] << endl;
else cout << 0 << endl;
}
}

浙公网安备 33010602011771号