这道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;
	}
}
posted @ 2022-07-18 23:14  seekerHeron  阅读(53)  评论(0)    收藏  举报